android之自定义Toast

这次接到交互的需求是,自下而上弹出一个Toast,持续4秒,渐隐消失(动画效果很简单,我就不贴代码了)。开发android的童鞋们都知道,Toast的duration时间只有Toast.LENGTH_LONG和Toast.LENGTH_SHORT,如果需要持续4秒,并且弹出、消失还要带着一些动画效果,那我只能自定义一个Toast了。

以下的R.layout.toast_custom你可以做成你需要的布局,可以携带图片的,可以只是文字的…

话不多说,直接上代码了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class CustomToast {
private WindowManager.LayoutParams mParams;
private long mDuration;
private static WindowManager mWindowManager;
private static View mToastView;
private Timer mTimer;
private CustomToast(Context context, String text, long duration){
//Toast的持续时间
mDuration = duration;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
//自定义一个你需要的toast.xml布局文件
mToastView = inflater.inflate(R.layout.toast_custom, null);
((TextView) mToastView.findViewById(R.id.tv_custom_desc)).setText(text);
mTimer = new Timer();
//设置布局参数
setParams();
}
public static CustomToast makeText(Context context, String text, long showTime) {
CustomToast result = new CustomToast(context, text, showTime);
return result;
}
private void setParams() {
mParams = new WindowManager.LayoutParams();
mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.format = PixelFormat.TRANSLUCENT;
//设置进入退出的动画效果
mParams.windowAnimations = R.style.toast_housedetail_show_anim;
mParams.type = WindowManager.LayoutParams.TYPE_TOAST;
mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
mParams.gravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
mParams.y = 200;
}
public void show(){
mWindowManager.addView(mToastView, mParams);
mTimer.schedule(new TimerTask() {
@Override
public void run() {
if (mToastView!=null) {
mWindowManager.removeView(mToastView);
mToastView = null;
mTimer.cancel();
}
}
}, mDuration);
}
public void cencel(){
if (mToastView!=null){
mWindowManager.removeView(mToastView);
mToastView = null;
mTimer.cancel();
}
}
}

因为我们的需求中在跳转到新的页面的时候,即使Toast没执行完,也要取消它,所以在onPause()方法中,我调用了这个cencel()。
调用方式如下:

1
2
3
4
CustomToastUtils customToast = CustomToast.makeText(this, "我是自定义的Toast", 4000);
customToast.show();
//在onPause()或onDestory()中可以调用cencel()
customToast.cencel();

到此,我本以为会是一个完美的Ending…

But,上述方法可能在小米的手机中失效,addView完全没有效果,那是因为小米手机默认关闭了悬浮窗的提示。

打开手机的设置-应用-找到该应用-权限-显示悬浮窗。

这样再去看看你自定义Toast的位置,应该就会弹出Toast了吧。有人可能会问,大部分的用户都会使用手机的默认权限,我们如果在代码里该怎么控制悬浮窗的开启?如果小米能让你用代码控制,就不会限制悬浮窗的使用了。但是你还可以用代码控制去打开权限页,让用户手动去开启这个悬浮窗的权限还是可以的。

我们的需求不允许这么做,控制权限在这篇文章里就不做过多的叙述了。大家应该能看出来我已经尽力了,我又不能根据不同的手机,在代码里做不同的逻辑来展示自定义的Toast。所以只能去砍交互的需求,最后达成一致的需求是,Toast持续3秒,按照原生Toast的动画效果来弹。根据UI设计的位置、形状、背景色以及文字的颜色和大小来展示。所以就有了如下的修改:

1
2
3
4
5
6
7
View view = getLayoutInflater().inflate(R.layout.toast_custom, null);
TextView tvCustomDesc = (TextView) view.findViewById(R.id.tv_custom_desc);
tvCustomDesc.setText("我是自定义的Toast");
mToast = new Toast(getApplicationContext());
mToast.setView(view);
mToast.setGravity(Gravity.BOTTOM, 0, DensityUtils.dp2px(60));
mToast.show();

没错,只是去掉了持续4秒,和弹出、消失的动画效果,代码量就从一个类,减少到7行。

如需转载,请注明出处:YauLam’s Blog,thank u~