简单粗暴,先看效果:
首先贴上工具类的代码:
/**
* 通用(主、子线程)的自定义Toast
*/
public class ToastUtil {
private static final String TAG = "ToastUtil";
private static Toast toast;
//如果只想在主线程中弹出自定义toast,则直接调用此方法即可
public static void showToast(Context context, String titles, String messages) {
toastProcess(context, titles, messages);
}
//如果想在子线程中和子线程中都能使用,则调用此方法即可(前提是在Activity中,因为runOnUiThread属于Activity中的方法)
public static void showToast1(final Activity context, final String titles, final String messages) {
if ("main".equals(Thread.currentThread().getName())) {
toastProcess(context, titles, messages);
} else {
context.runOnUiThread(new Runnable() {
@Override
public void run() {
toastProcess(context, titles, messages);
}
});
}
}
/**
* 自定义toast
*
* @param context 上下文对象
* @param titles toast 标题
* @param messages toast内容
*/
private static void toastProcess(Context context, String titles, String messages) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert layoutInflater != null;
View view = layoutInflater.inflate(R.layout.custom_toast, null);
ImageView bg = view.findViewById(R.id.toast_bg);
TextView title = view.findViewById(R.id.toast_title);
TextView text = view.findViewById(R.id.toast_content);
bg.setImageResource(R.mipmap.toast_bg);//toast背景
title.setText(titles); //toast的标题
text.setText(messages); //toast内容
if (toast == null) {
toast = new Toast(context.getApplicationContext());
}
toast.setGravity(Gravity.CENTER, 12, 20);//setGravity用来设置Toast显示的位置,相当于xml中的android:gravity或android:layout_gravity
toast.setDuration(Toast.LENGTH_LONG);//setDuration方法:设置持续时间,以毫秒为单位。该方法是设置补间动画时间长度的主要方法
toast.setView(view); //添加视图文件
toast.show();
}
}
上述代码中封装了2个toast方法,注释上已经很明白了。
关注2个重点:
(1).自定义toast
(2).可在子线程中使用
(1).自定义toast
上述代码展示了自定义toast的代码逻辑(做了封装toastProcess(....)),下面讲toast的自定义布局也贴出来,custom_toast.xml
(2).可在子线程中使用
这个也没啥好讲的,代码已经体现出来了。首先 通过Thread.currentThread().getName()方法获取当前线程的线程名称,如果等于"main"的话,则说明在主线程,否则在子线程。这里需要注意的是,所谓的子线程通用,其实也是有限制条件的,那就是传入的上下文对象必须是Activity,因为context.runOnUiThread()方法的context只能在其是Activity中才能使用。这里暂时不考虑service中弹出toast的情况,毕竟toast也是属于用户交互的一种,service主要用于不直接与用户交互的后台,使用toast的情况并不常见。。。
除此之外,我想说的是,如果不作为toast通用工具类来讲的话,完全可以只在ToastUtil中实现自定义toast的部分,而在主程序中通过handler来实现线程间通信,最后只要保证在ui线程中调用ToastUtil.showToast(...)方法即可。
贴出最初的MainActivity.java代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button customToast;
private Button threadCustomToast;
private static MyHandler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customToast = findViewById(R.id.custom_toast);
threadCustomToast = findViewById(R.id.thread_custom_toast);
customToast.setOnClickListener(this);
threadCustomToast.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.custom_toast:
ToastUtil.showToast(MainActivity.this, "这是一个toast", "我就是那个toast");
break;
case R.id.thread_custom_toast:
myHandler = new MyHandler(this);
myHandler.post(myRunnable);
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandler.removeCallbacks(myRunnable);
myHandler = null;
}
//******************************************************
/**
* 创建静态内部类
*/
private static class MyHandler extends Handler {
//持有弱引用HandlerActivity,GC回收时会被回收掉.
private final WeakReference mActivty;
MyHandler(MainActivity activity) {
mActivty = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0x01:
MainActivity activity = mActivty.get();
if (activity != null) {
//执行业务逻辑
String text = (String) msg.obj;
ToastUtil.showToast(activity, "这是一个toast", text);
}
break;
default:
break;
}
}
}
private Runnable myRunnable = new Runnable() {
@Override
public void run() {
//线程中无法使用Toast,需要将Toast发送至主线程中才能使用
Message msg = new Message();
msg.what = 0x01;
msg.obj = "这是线程的toast";
myHandler.sendMessage(msg);
}
};
}
上述代码,仅供读者参考吧,毕竟如果存在多个不同的子线程的话,如此操作还是比较繁琐的,不如工具类来的方便啊。
好啦,到此结束,如果有什么疑问,或者意见或建议,请留言探索。