自定义toast的学习(改变toast默认动画、弹出位置)
项目里用到了一个DrawerToast,查了一下是这位兄弟的东西:http://blog.csdn.net/pmavio/article/details/38817885
主要实现了不用等待toast的队列直接往上叠加、toast的动画自定义等效果。
根据需求主要要改动的有几点:
1.toast的位置,要在titlebar正下方。
2.当第二个toast出现的时候,不往上叠加,停止前面toast的动画、直接在同样位置显示第二个toast。
3.每种系统都有个默认的toast动画效果,这个会跟自定义的动画叠加,没办法达到预计的效果。
因为我很懒··所以直接在源码上面改动了。
toast的位置
1.DrawerToast的原理思路就是在toast.setView的时候传入若干布局,最后把需要显示的view都放到一个LinearLayout里做垂直的线性显示,看了一下源码,把initViews里的
mView.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM);改成mView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);以满足我要的置顶的功能。
一跑程序发现toast还相对屏幕上方缩进去了一点,检查代码发现
LayoutParams params = new LayoutParams(screenWidth, screenHeight); mTopView2.setLayoutParams(params);
这边在初始化的时候用了屏幕的高度,这个高度还包括了android系统的状态栏,所以高度是超过应用本身的。然后不知道是由于什么原因导致这个view多出来的部分不是向下面延伸,是缩到屏幕上方去了。所以在初始化的时候,高度扣掉状态栏高度,再设置titlebar高度的margin,解决第一个问题
//状态栏高度 public static int getStatusBarHeight(Context context) { Class<?> c = null; Object obj = null; Field field = null; int x = 0, statusBarHeight = 0; try { c = Class.forName("com.android.internal.R$dimen"); obj = c.newInstance(); field = c.getField("status_bar_height"); x = Integer.parseInt(field.get(obj).toString()); statusBarHeight = context.getResources().getDimensionPixelSize(x); } catch (Exception e1) { e1.printStackTrace(); } return statusBarHeight; } int statusBarHeight = getStatusBarHeight(mContext); LayoutParams params = new LayoutParams(screenWidth, screenHeight - statusBarHeight); mTopView2.setLayoutParams(params);
2.第二个问题好办,只要每次toast要show的时候把之前已经add进去的viewremove掉就可以了。
在show方法里的mView.addView(v, 0);前面加上mView.removeAllViews();
3.这个问题很讨厌,本来以为设了动画本身的默认动画应该就不见了,查了一下才发现每个系统的默认toast的动画效果跟后面设的是不冲突的,可以同时存在,所以还必须得去掉系统默认的动画。
由于DrawerToast本身已经有用反射去获得mTN下的show和hide方法,所以只要在原先的代码稍做改动就好了
/** * 通过反射获得mTN下的show和hide方法 */ private void initTN() { mToast = new Toast(mContext); mToast.setView(mTopView); Class<Toast> clazz = Toast.class; try { mTN = clazz.getDeclaredField("mTN"); mTN.setAccessible(true); mObj = mTN.get(mToast); // 取消掉各个系统的默认toast弹出动画 modify by yangsq 2014-01-04 Field field = mObj.getClass().getDeclaredField("mParams"); if (field != null) { field.setAccessible(true); Object mParams = field.get(mObj); if (mParams != null && mParams instanceof WindowManager.LayoutParams) { WindowManager.LayoutParams params = (WindowManager.LayoutParams) mParams; params.windowAnimations = -1; } } showMethod = mObj.getClass().getDeclaredMethod("show", null); hideMethod = mObj.getClass().getDeclaredMethod("hide", null); hasReflectException = false; } catch (NoSuchFieldException e) { hasReflectException = true; System.out.println(e.getMessage()); } catch (IllegalAccessException e) { hasReflectException = true; System.out.println(e.getMessage()); } catch (IllegalArgumentException e) { hasReflectException = true; System.out.println(e.getMessage()); } catch (NoSuchMethodException e) { hasReflectException = true; System.out.println(e.getMessage()); } }
最后就是在调用show的时候传入需要的开始和结束动画了,这边根据自己的需求来传,就不多说了。