自定义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的时候传入需要的开始和结束动画了,这边根据自己的需求来传,就不多说了。

posted @ 2015-01-14 18:53  幻次元  阅读(6968)  评论(0编辑  收藏  举报