Android 开发之自定义Toast的显示时长

众所周知,Toast的显示时长是固定的,一个short是2s,一个long是3.5s。而且Google并未给出相关的接口让我们去设置这个时长。

上半年做项目有用到Toast,而且刷新频率比较高(1s一次)用short的时长也搞不定。

如果仅仅为了实现这个功能,那么Dialog、PopupWindow也是比较容易实现的,但效率就无法保证了。秉着专研的精神,还是看了下Toast的源码。

Toast显示的时候是把它加到一个toast队列中,然后判断是否重复,前面是否有正在显示的toast等等过程,实现起来还是挺复杂的。

(部分网友的启发)看到Toast的源码,Toast类有一个TN对象mTN,这个对象有show和hide两个方法(都是隐藏的),

于是猜测着两个方法应该能够控制Toast的显示和关闭,于是试着用反射的方式实现这两个方法,结果还可以,那么接下来自定义时长就是件很容易的事情了。但有个问题,这方法

在Android SDK 2.3 上跑没问题,但换到我的手机(4.0.3)就不可用。

看来两版SDK还是差异挺大,这问题留待有时间再研究。废话不多说,贴我的代码:

package com.lqh.widget;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Timer;import java.util.TimerTask;import android.content.Context;import android.os.AsyncTask;import android.os.Handler;import android.os.Message;import android.widget.Toast;/** * 可控制显示和隐藏时间的Toast. * SDK 2.3 可用, SDK 3.0 以上不行 * @author krusca * */public class LToast{Method mShowMethod;Method mHideMethod;Field mTNField;Object mObject;public static LToast create(Toast toast){LToast lt = new LToast();try {lt.mTNField = toast.getClass().getDeclaredField("mTN");//获得mToast对象内的mTN变量lt.mTNField.setAccessible(true);//可进入该对象lt.mObject = lt.mTNField.get(toast);//获取mTN变量在mToast对象中的具体值lt.mShowMethod = lt.mObject.getClass().getDeclaredMethod("show", null);//进而获取mTN对象的show方法lt.mHideMethod = lt.mObject.getClass().getDeclaredMethod("hide", null);//进而获取mTN对象的hide方法} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}return lt;}public static LToast create(Context context, String msg){Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);return create(toast);}public static LToast create(Context context, int resId){Toast toast = Toast.makeText(context, resId, Toast.LENGTH_SHORT);return create(toast);}/*** 自定义一个时间,使Toast显示这段时间后消失* @param context* @param msg 内容* @param duration 时间间隔,单位为ms*/public static void show(Context context, String msg, int duration){final LToast lToast = create(context, msg);lToast.showToast();new Timer().schedule(new TimerTask() {public void run() {synchronized(mHandler){mHandler.obtainMessage(0xF1, lToast).sendToTarget();}}}, duration);}/*** 自定义一个时间,使Toast显示这段时间后消失* @param context* @param resId 内容* @param duration 时间间隔,单位为ms*/public static void show(Context context, int resId, int duration){show(context, context.getResources().getString(resId), duration);}public void showToast(){try {mShowMethod.invoke(mObject, null);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}public void hideToast(){try {mHideMethod.invoke(mObject, null);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}private static Handler mHandler = new Handler(){public synchronized void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what == 0xF1){LToast temp = (LToast)msg.obj;temp.hideToast();}}};}

本例对自定义Toast进行了很好的封装,

利用反射机制,将Toast的mTN对象拿了出来,然后再利用反射机制调用其show和hide方法。

由于SDK 3.0 以上的不支持,此功能还是无法得到广泛的使用,仅当做对反射机制的一种学习和复习吧。

版权声明:本文为博主原创文章,未经博主允许不得转载。

,不要害怕错过什么,因为在路上你就已经收获了自由自在的好心情。

Android 开发之自定义Toast的显示时长

相关文章:

你感兴趣的文章:

标签云: