android的toast怎么自定义显示时间长度?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android的toast怎么自定义显示时间长度?相关的知识,希望对你有一定的参考价值。
android新手求解
Android中Toast的显示时间为特定时间且不可更改,但是有时候我们开发设计需要让Toast显示更长时间,或者自己完全控制Toast的显示和关闭。通过查看Toast类的源码,可以看出,这有点难为它了,Toast类本身并没有提供相应方法。但是通过源码的查看,还是可以看出点眉头。源码分析思路在这里转eoe里的一篇文章,思路较为清晰:
转:
Toast信息提示框之所以在显示一定时间后会自动关闭,是因为在系统中有一个Toast队列。系统会依次从队列中取(出队列)一个Toast,并 显示它。在显示一段时间后,再关闭,然后再显示下一个Toast信息提示框。
直到Toast队列中所有Toast都显示完为止。那么有些时候需要这个Toas t信息提示框长时间显示,直到需要关闭它时通过代码来控制,而不是让系统自动来关闭Toast信息提示框。
不过这个要求对于Toast本身来说有些过 分,因为Toast类并没有提供这个功能。虽然如此,但方法总比问题多。通过一些特殊的处理还是可以实现这个功能的,而且并不复杂。
Toast信息提示框需要调用Toast.show方法来显示。下面来看一下show方法的源代码。
public void show()
if (mNextView == null)
throw new RuntimeException("setView must have been called");
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
try
// 将当前Toast加入到Toast队列
service.enqueueToast(pkg, tn, mDuration);
catch (RemoteException e)
// Empty
复制代码
show方法的代码并不复杂,可以很容易找到如下的代码。
service.enqueueToast(pkg, tn, mDuration);
复制代码
从上面的代码可以很容易推断出它的功能是将当前的Toast加入到系统的Toast队列中。
看到这里,各位读者应该想到。虽然show方法的表面功能是显示Toast信息提示框,但其实际的功能是将Toast加入到队列中,再由系统根据Toast队列来显示Toast信息提示框。那么我们经过更进一步地思考,可以大胆地做出一个初步的方案。
既然系统的Toast队列可以显示Toast信息提示框,那么我们为什么不可以自己来显示它呢?
这样不是可以自己来控制Toast的信息提示框的显示和关闭了吗!当然,这就不能再调用show方法来显示Toast信息提示框了(因为show方法会将Toast加入队列,这样我们就控制不了Toast了)。
既然初步方案已拟定,现在就来实施它。先在Toast类找一下还有没有其他的show方法。
结果发现了一个TN类,该类是Toast的一个内嵌类。在TN类中有一个show方法。TN是ITransientNotification.Stub的子类。从ITransientNotification和TN类中的show方法初步推断(因为Transient的中文意思是“短暂的”)系统是从Toast队列中获得了Toast对象后,利用TN对象的show方法显示Toast,再利用TN.hide方法来关闭Toast。
首先声明,这只是假设,我们还不知道这么做是否可行!当然,这也是科学研究的一般方法,先推断或假设,然后再证明推断或假设。
现在关键的一步是获得TN对象。遗憾的是TN被声明成private类型,外部无法访问。不过别着急。在Toast类中有一个mTN变量。虽然不是public变量,但仍然可以通过反射技术访问该变量。mTN变量会在创建Toast对象时初始化。
因此,只要获得mTN变量,就获得了TN对象。下面的代码显示了一个永远不会自动关闭的Toast信息提示框。
// 先创建一个Toast对象 Toast toast = Toast.makeText(this, "永不消失的Toast", Toast.LENGTH_SHORT); // 设置Toast信息提示框显示的位置(在屏幕顶部水平居中显示) toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0); try
// 从Toast对象中获得mTN变量 Field field = toast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
Object obj = field.get(toast);
// TN对象中获得了show方法
Method method = obj.getClass().getDeclaredMethod("show", null);
// 调用show方法来显示Toast信息提示框
method.invoke(obj, null);
catch (Exception e)
复制代码
上面的代码中try…catch(…)…语句中的代码是关键。先利用事先创建好的Toast对象获得了mTN变量。然后再利用反射技术获得了TN对象的show方法。
关闭Toast和显示Toast的方法类似,只是需要获得hide方法,代码如下:
try
// 需要将前面代码中的obj变量变成类变量。这样在多个地方就都可以访问了
Method method = obj.getClass().getDeclaredMethod("hide", null);
method.invoke(obj, null);
catch (Exception e)
复制代码
上面的代码已经很完美地实现了通过代码控制Toast信息提示框显示和关闭的功能。
但如果想实现得更完美,可以在Android SDK源代码中找一个叫ITransientNotification.aidl的文件(该文件是AIDL服务定义文件,将在后面详细介绍),并在Android工程的src目录中建一个android.app包,将这个文件放到这个包中。
然后ADT会自动在gen目录中生成了一个android.app包,包中有一个ITransientNotification.java文件。由于Android SDK自带的ItransientNotification接口属于内部资源,外部程序无法访问,因此,只能将从Toast对象中获得的mTN变量转换成刚才生成的ITransientNotification对象了。
这样就不需要使反射技术获得show和hide方法了。
经过改良的显示和关闭Toast信息提示框的代码如下:
ITransientNotification notification = (ITransientNotification) field.get(toast);
// 显示Toast信息提示框
notification.show();
// 关闭Toast信息提示框
notification.hide();
复制代码
最后整理代码如下:
Java代码
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class TestToastActivity extends Activity
private Button showtoast,closetoast;
private Toast toast;
private Field field;
private Object obj;
private Method showMethod,hideMethod;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化按钮组件
showtoast = (Button)this.findViewById(R.id.showtoast);
closetoast = (Button)this.findViewById(R.id.closetoast);
//设置组件监听
showtoast.setOnClickListener(new MyOnClickListener());
closetoast.setOnClickListener(new MyOnClickListener());
//创建Toast对象
toast = Toast.makeText(this, "Toast自定义显示时间测试", 1);
toast.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
//利用反射技术拿到mTN对象
reflectionTN();
class MyOnClickListener implements View.OnClickListener
@Override
public void onClick(View v)
switch (v.getId())
case R.id.showtoast:
try
showMethod.invoke(obj, null);//调用TN对象的show()方法,显示toast
catch (Exception e)
e.printStackTrace();
break;
case R.id.closetoast:
try
hideMethod.invoke(obj, null);//调用TN对象的hide()方法,关闭toast
catch (Exception e)
e.printStackTrace();
break;
default:
break;
private void reflectionTN()
try
field = toast.getClass().getDeclaredField("mTN");
field.setAccessible(true);
obj = field.get(toast);
showMethod = obj.getClass().getDeclaredMethod("show", null);
hideMethod = obj.getClass().getDeclaredMethod("hide", null);
catch (Exception e)
e.printStackTrace();
复制代码 参考技术A 假如:
Toast.makeText(context,msg,Toast.LENGTH_SHORT).show(); 这个是短时时间显示;
Toast.makeText(context,msg,Toast.LENGTH_LONG).show(); 这个是长时时间显示; 参考技术B 只有long 和shot两种模式。。
Android快速开发常用知识点系列目录
项目构建
Android多Module下的Application引用方式
APP开篇
Android APP应用启动页白屏(StartingWindow)优化
Android6.0运行时权限(基于RxPermission开源库)
Toast篇章
ToastUtil【简单的Toast封装类】【未自定义Toast的显示风格】
ToastCustomUtil【简单的Toast封装类】【自定义Toast的显示风格】
Log篇章
LogcatHelperDemo【应用log信息保存成本地文件】
常用util工具类篇章
ColorUtil【Color工具类(color整型、rgb数组、16进制互相转换)】
DensityUtil【尺寸转换工具类(px、dp互相转换)】
WebUtils【MD5加密(基于MessageDigest)】
ACache【轻量级的开源缓存框架】【不建议使用】
PreferencesUtils【SharedPreferences操作工具类】
DateTimeHelper【日期类型与字符串互转以及日期对比相关操作】
DeviceUuidFactory【获取设备唯一标识码的UUID(加密)】【需要运行时权限的处理的配合】
IntentActionUtil【Intent的常见作用的工具类】
FileUtils【获取SD卡根目录、读写文件、移动、复制、删除文件、获取文件名、后缀名操作类】【不建议使用这个工具类】
GetPathFromUri4kitkat【Android 4.4 kitkat以上及以下根据uri获取路径的方法】
AssetsUtils【读取assets、res/raw、./data/data/包名/目录下的文件】
AntZipUtils【基于Ant的Zip压缩解压缩工具类】
ResDrawableImgUtil【根据图片名称获取resID值或者Bitmap对象】
BitmapUtil【缩放bitmap以及将bitmap保存成图片到SD卡中】
Cache【硬盘缓存工具类(包含内存缓存LruCache和磁盘缓存DiskLruCache)】
KeyboardUtil【软键盘弹出后输入框上移一定的高度】
EscapeAndUnescapeUtil【java模拟js的escape和unescape函数】
ShareIntentUtil【调用系统自带的分享的工具类】
NotificationSetUtilDemo【判断APP通知栏权限是否开启,以及如何跳转到应用程序设置界面】
RomUtil【Android判断手机ROM,用于判断手机机型】
Activity跳转篇章
Activity、Fragment、Dialog基类简单整理
ActivityJump+ActivityManager【Activity之间的跳转和Activity任务栈管理】
下拉菜单篇章
SpinnerViewPop【PopWindow样式(单选)、Dialog样式(单选+多选)的下拉菜单】
Android-PickerView【仿iOS的PickerView控件,并封装了时间选择和选项选择这两种选择器】使用
对话框篇章
ProgressWheelDialogUtil【ProgressWheel Material样式进度条对话框】
ConfirmCancelUtilDialog【确认取消对话框封装类】
AlertConfirmDialog【基于AlertDialog的确认取消对话框】
ConfirmCancelBottomSheetDialog【确认取消底部对话框】
ArticleRemoveDelDialog【基于AlertDialog的回收删除对话框】
NormalDialogFragmentDemo【普通页面的DialogFragment】
NewBuiltBottomSheetDialog【新建底部对话框】
PopupWindowMenuUtil【popupwindow样式菜单项列表】
MaterialCalendarDialog【Material样式的日历对话框】
网络请求篇章
okhttputils【 Android 一个改善的okHttp封装库】使用(一)
okhttputils【 Android 一个改善的okHttp封装库】使用(二)
okhttputils【 Android 一个改善的okHttp封装库】使用(三)
发现新版本篇章
数据库篇章
Litepal【开源数据库ORM框架】【版本是1.6.1,需要升级到2.0.0】
LitepalNewDemo【开源数据库ORM框架-LitePal2.0.0版本的使用】
选项卡篇章
TabBottomFragmentLayout【自定义底部选项卡区域(搭配Fragment)】【有时候会这样用,有时候使用FragmentTabHost】
TabTopLayout【自定义顶部选项卡区域(固定宽度且居中)】【有时候会这样用】
TabTopUnderLineLayout【自定义顶部选项卡(带下划线)】【了解即可】
TabTopAutoLayout【自定义顶部选项卡区域(带下划线)(动态选项卡数据且可滑动)】【一般使用TabLayout+ViewPager】
TabTopAutoTextSizeLayout【自定义文字字号区域(动态选项卡数据且可滑动)】
FragmentTabHostBottomDemo【FragmentTabHost + Fragment实现底部选项卡】
FragmentTabHostTopDemo【FragmentTabHost固定宽度且居中】【演示部分功能的用法】
FragmentTabHostUnderLineDemo【FragmentTabHost带下划线】【演示部分功能的用法】
FragmentTabHostAutoDemo【FragmentTabHost可滑动的选项卡】【演示部分功能的用法】【一般使用TabLayout+ViewPager】
TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】
TabLayoutBottomDemo【TabLayout实现底部选项卡】【一般不这样用】
EditText输入框篇章
DownEditTextView【自定义Edittext对Android 软键盘向下的监听】
RecyclerView篇章
RecyclerViewItemTouchHelperDemo【使用ItemTouchHelper进行拖拽排序功能】
RecyclerSwipeAdapterDemo【使用AndroidSwipeLayout用于列表项侧滑功能】
RecyclerFullyManagerDemo【ScrollView里嵌套Recycleview的自适应高度功能】
RecyclerViewSelectableAdapterDemo【封装BaseSelectableAdapter用于多选、单选,以及切换选中状态等功能】
RecyclerViewLoadMoreDemo【封装上拉加载功能的RecyclerView,搭配SwipeRefreshLayout实现下拉刷新】
RecyclerFlexboxLayoutManagerDemo【使用FlexboxLayoutManager实现流式布局】
VLayoutDemo【VLayout的简单使用demo(基于V1.2.8版本)】
Glide篇章
GlideDemo【Glide3.7.0版本的简单使用以及圆角功能】
GlideNewDemo【Glide4.7.1版本的简单使用以及圆角功能】
PhotoPicker篇章
PhotoPickerDemo【PhotoPicker0.9.8的个性化修改以及使用(内部glide版本号是3.7.0)】
PhotoPickerNewDemo【PhotoPicker0.9.12的个性化修改以及使用(内部glide版本号是4.1.1)】
WebView篇章
MyWebViewDemo【封装Webview常用配置和选择文件、打开相机、录音、打开本地相册的用法】
MyBridgeWebViewDemo【集成JsBridge开源库的的封装的webview】
MyX5TbsPlusDemo【体验腾讯浏览服务Android SDK (TbsPlus 版)】
MyX5TbsDemo【体验腾讯浏览服务Android SDK (完整版)】
多语言篇章
Material Design篇章
ToolbarDemo【Toolbar作为顶部导航栏的简单使用】
DrawerLayoutDemo【侧边栏(侧滑菜单)简单实现】
NavigationViewDemo【和DrawerLayout搭配使用实现侧滑导航视图界面】
FloatingActionButtonDemo【悬浮按钮的使用,顺带snackBar的使用】
SnackbarUtilDemo【Snackbar的封装类】
CollapsingToolbarLayoutDemo【可折叠式标题栏,顺便带有CardView卡片式布局】
ConstraintLayoutDemo【约束性布局知识梳理】【基于1.1.3】
ViewPager篇章
ViewPagerWithRecyclerDemo【RecyclerView+ViewPager实现类似TabLayout+ViewPager效果】
ViewPagerWithViewDemo【ViewPager和View搭配以及演示获取里面的值和CheckBox单选效果】
ViewPagerWithImageDemo【ViewPager如何判断滑动到第一页和最后一页以及弹出对话框功能】
百度篇章
BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.7.3)
BaiduSpeechDemo【百度语音SDK集成】(基于v3.0.8.1)
友盟篇章
UmengAppDemo【友盟统计SDK集成以及多渠道打包配置,基于V7.5.3版本】
UmengShareDemo【友盟分享SDK集成,基于V6.9.3版本】
推送篇章
HWPushDemo【华为推送集成,基于2.6.1.301版本】
XiaomiPushDemo【小米推送集成,基于V3.6.12版本】
轮播图控件篇章
其他篇章
ShortcutBadgerDemo【安卓应用角标(badge)实现方案】
Android根据word模板文档将表单数据生成word文档的方案整理
Android加密篇章
以上是关于android的toast怎么自定义显示时间长度?的主要内容,如果未能解决你的问题,请参考以下文章