UI--Toast自定义时间(一) 反射

来源:互联网 发布:邹倚天 知乎 编辑:程序博客网 时间:2024/06/10 06:21

      我们知道Toast在一般情况下只能设置两个时间:Toast.LENGTH_LONG和Toast.LENGTH_SHORT,在源码中对应NotificationManagerService这个类中的两个变量:LONG_DELAY = 3000(3秒) 和SHORT_DELAY = 2500 (2秒),怎样才能自己控制Toast的显示时间呢?

          方法大致有这几种:

           1.利用反射。

           2.重写Toast。

           3.使用popwindow模仿出Toast,自定义显示时间。

           4.根据源码中windowmanager自定义实现Toast。

           5.结合Timer.

     首先我们来看看Toast源码中的show方法:

       

    /**     * Show the view for the specified duration.     */    public void show() {        if (mNextView == null) {            throw new RuntimeException("setView must have been called");        }        INotificationManager service = getService();        String pkg = mContext.getPackageName();        TN tn = mTN;        tn.mNextView = mNextView;        try {            service.enqueueToast(pkg, tn, mDuration);        } catch (RemoteException e) {            // Empty        }    }

      

// =======================================================================================    // All the gunk below is the interaction with the Notification Service, which handles    // the proper ordering of these system-wide.    // =======================================================================================    private static INotificationManager sService;    static private INotificationManager getService() {        if (sService != null) {            return sService;        }        sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));        return sService;    }


      Toas的show()使用单例模式得到了一个INotification实例,并且实例化了一个TN类将其作为参数传进了INotification的enqueueToast()方法中,
不难发现,在这段代码中INotificationManager和TN是个关键类,那么继续看:

private static class TN extends ITransientNotification.Stub {        final Runnable mShow = new Runnable() {            @Override            public void run() {                handleShow();            }        };<pre name="code" class="java">       /**         * schedule handleShow into the right thread         */        @Override        public void show() {            if (localLOGV) Log.v(TAG, "SHOW: " + this);            mHandler.post(mShow);        }        /**         * schedule handleHide into the right thread         */        @Override        public void hide() {            if (localLOGV) Log.v(TAG, "HIDE: " + this);            mHandler.post(mHide);        }
}

   在TN类中,show()和hide()方法 控制Toast的显示和隐藏,主要的分析完了,剩下的有兴趣就留给大家自己去看了咯,总结就是:

   

    系统内部会有一个队列来管理多个Toast,调用的show()方法不会直接显示,而是先进入队列,由Toast队列来管理是否show()和hide(),我们想要自己控制显示和隐藏,那么我们就需要直接调用TN中show()和hide()方法。

  知道了原因,那么我们就可以开始实践了。

   一:利用反射

       

     核心代码:

      Context context = getApplicationContext(); //得到上下文      Toast toast = Toast.makeText(context , "利用反射控制显示时间",Toast.LENGTH_SHORT); //先实例化一个Toast

 <pre name="code" class="java">       // 显示Toast        try{            Field field = toast.getClass().getDeclaredField("mTN"); //得到mTN成员变量            field.setAccessible(true);            Object object = field.get(toast);             Method method = object.getClass().getDeclaredMethod("show",null);//得到mTN对应类的方法            method.invoke(object,null);        }        catch (Exception e){           e.printStackTrace();        }

     // 隐藏Toast        try{            Method method = object.getClass().getDeclaredMethod("hide",null);//得到mTN对应类的方法            method.invoke(object,null);        }        catch (Exception e){           e.printStackTrace();        }


     核心代码就是这样,各位可以自己封装出来使用,android4.0版本以上貌似不可用。


     剩下的几种方法,会在后续的文章中贴出,敬请期待~


     ps: 今天是大年初一,祝大家新春快乐~



   

   


       

    

0 0
原创粉丝点击