关于Toast的一些常见操作
程序员文章站
2022-06-11 22:13:57
...
创建一个单例的Toast
使用场景
Toast也被称为吐司,比如说现在有两个地方弹一个吐司,当用户点击了A地方的时候吐司之后,又马上切换到B地方吐司,如果是没有使用单例的话,那么当弹起第一个吐司的时候,时间就会有2-3S的间隔才会弹出第二个吐司.那么给用户的体验就会非常不好.
默认的Toast写法
//如果是使用studio的话,可以打Toast就可以快速的写出这行代码,记得T必须是要大写,否则无法弹出对应的选项
Toast.makeText(MainActivity.this, "这是默认效果的Toast", Toast.LENGTH_LONG).show();
单例Toast:
public class ToastUtil {
/**
* 第一次弹吐司的string
*/
private static String oldMsg;
protected static Toast toast = null;
/**
* 第一次弹吐司的时间
*/
private static long oneTime = 0;
/**
* 再次弹吐司的时间
*/
private static long twoTime = 0;
public static void showToast(Context context, String s) {
if (toast == null) {
toast = Toast.makeText(context, s, Toast.LENGTH_SHORT);
toast.show();
oneTime = System.currentTimeMillis();//当前系统的时间
} else {
twoTime = System.currentTimeMillis();//再次获取系统的时间
//判断传入的string是否与之前传入的string相同
if (s.equals(oldMsg)) {
//判断两次获取的当前系统时间是否超过默认的吐司时间,超过就再次吐司,否则就不再吐司
if (twoTime - oneTime > Toast.LENGTH_SHORT) {
toast.show();
}
} else {
oldMsg = s;
toast.setText(s);
toast.show();
}
}
oneTime = twoTime;
}
public static void showToast(Context context, int resId) {
showToast(context, context.getString(resId));
}
}
表面上看没什么问题,但是在真实运用过程中,就会出现内存泄漏的问题。原因也很简单,当弹出一个toast的时候,当前页面关闭,但是toast还是引用了context。导致无法GC。所以应该将context变成context.getApplicationContext()。
最终的代码:
public class ToastUtil {
/**
* 第一次弹吐司的string
*/
private static String oldMsg;
protected static Toast toast = null;
/**
* 第一次弹吐司的时间
*/
private static long oneTime = 0;
/**
* 再次弹吐司的时间
*/
private static long twoTime = 0;
public static void showToast(Context context, String s) {
if (toast == null) {
toast = Toast.makeText(context.getApplicationContext(), s, Toast.LENGTH_LONG);
toast.show();
oneTime = System.currentTimeMillis();//当前系统的时间
} else {
twoTime = System.currentTimeMillis();//再次获取系统的时间
if (s.equals(oldMsg)) {//判断两次的string是否相同
if (twoTime - oneTime > Toast.LENGTH_LONG) {//判断两次获取的当前系统时间是否超过默认的吐司时间,超过就再次吐司,否则就不再吐司
toast.show();
}
} else {
oldMsg = s;
toast.setText(s);
toast.show();
}
}
oneTime = twoTime;
}
public static void showToast(Context context, int resId) {
showToast(context, context.getString(resId));
}
}
自定义Toast
自定义显示位置
Toast toast = Toast.makeText(MainActivity.this, "这是自定义位置的Toast", Toast.LENGTH_LONG);
//设置Toast在屏幕上显示的位置
toast.setGravity(Gravity.CENTER, 20,80);
toast.show();
自定义显示图标:
Toast toast = Toast.makeText(MainActivity.this, "这是带图片的Toast", Toast.LENGTH_LONG);
//创建一个子布局用于自定义Toast的内容
LinearLayout toastView = (LinearLayout) toast.getView();
//在这个子布局中定义一个ImageView用于添加Toast显示的图片
ImageView iv= new ImageView(MainActivity.this);
iv.setImageResource(R.drawable.p3);
//把ImageView添加到子布局当中
toastView.addView(iv, 0);
toast.show();
完全自定义的:
//创建一个布局,用于承载Toast中的内容
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.cell, null);
//Toast中的内容之一ImageView用于显示图片
ImageView iv = (ImageView) view.findViewById(R.id.iv);
iv.setImageResource(R.drawable.p4);
//Toast中的内容之二TextView用于显示Toast的标题
TextView title = (TextView) view.findViewById(R.id.tv_title);
title.setText("注意:");
//Toast中的内容之三TextView用于显示Toast的信息内容
TextView text = (TextView) view.findViewById(R.id.tv_message);
text.setText("这是完全自定义Toast");
//创建一个Toast对象
Toast toast = new Toast(MainActivity.this);
//设置Toast的显示位置为屏幕的右上方
toast.setGravity(Gravity.RIGHT | Gravity.TOP, 100,100);
//设置Toast的显示时间
toast.setDuration(Toast.LENGTH_LONG);
//设置Toast显示的布局
toast.setView(view);
toast.show();
其实就是将一个布局文件显示在Toast上
在线程中使用:
Handler handler = new Handler();
public void showToast() {
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "线程中的Toast", Toast.LENGTH_LONG).show();
}
});
}
new Thread(new Runnable() {
public void run() {
showToast();
}
}).start();
如果直接在子线程Toast,那么就会报错,:Can’t create handler inside thread that has not called Looper.prepare().至于为什么会这样大家可以参考这个链接.上面有讲的很清楚.