首页 > 代码库 > 自定义toast的学习(改变toast默认动画、弹出位置)

自定义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);
View Code

这边在初始化的时候用了屏幕的高度,这个高度还包括了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);
View Code

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());        }    }
View Code

最后就是在调用show的时候传入需要的开始和结束动画了,这边根据自己的需求来传,就不多说了。

自定义toast的学习(改变toast默认动画、弹出位置)