当前位置: 移动技术网 > IT编程>移动开发>Android > Android开发技巧之永不关闭的Toast信息框(长时间显示而非系统关闭)

Android开发技巧之永不关闭的Toast信息框(长时间显示而非系统关闭)

2019年07月24日  | 移动技术网IT编程  | 我要评论

苏州房价,瑞鸟的报复,86ps

toast信息提示框之所以在显示一定时间后会自动关闭,是因为在系统中有一个toast队列。系统会依次从队列中取(出队列)一个toast,并显示它。在显示一段时间后,再关闭,然后再显示下一个toast信息提示框。直到toast队列中所有toast都显示完为止。那么有些时候需要这个toast信息提示框长时间显示,直到需要关闭它时通过代码来控制,而不是让系统自动来关闭toast信息提示框。不过这个要求对于toast本身来说有些过分,因为toast类并没有提供这个功能。虽然如此,但方法总比问题多。通过一些特殊的处理还是可以实现这个功能的,而且并不复杂。

从7.3.1节的内容可以知道,toast信息提示框需要调用toast.show方法来显示。下面来看一下show方法的源代码。
复制代码 代码如下:

publicvoidshow(){
if(mnextview==null){
thrownewruntimeexception("setviewmusthavebeencalled");
}
inotificationmanagerservice=getservice();
stringpkg=mcontext.getpackagename();
tntn=mtn;
try{
//将当前toast加入到toast队列
service.enqueuetoast(pkg,tn,mduration);
}catch(remoteexceptione){
//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对象
toasttoast=toast.maketext(this,"永不消失的toast",toast.length_short);
//设置toast信息提示框显示的位置(在屏幕顶部水平居中显示)
toast.setgravity(gravity.top|gravity.center_horizontal,0,0);
try
{
//从toast对象中获得mtn变量
fieldfield=toast.getclass().getdeclaredfield("mtn");
field.setaccessible(true);
objectobj=field.get(toast);
//tn对象中获得了show方法
methodmethod=obj.getclass().getdeclaredmethod("show",null);
//调用show方法来显示toast信息提示框
method.invoke(obj,null);
}
catch(exceptione)
{
}

上面的代码中try{…}catch(…){…}语句中的代码是关键。先利用事先创建好的toast对象获得了mtn变量。然后再利用反射技术获得了tn对象的show方法。
关闭toast和显示toast的方法类似,只是需要获得hide方法,代码如下:
复制代码 代码如下:

try
{
//需要将前面代码中的obj变量变成类变量。这样在多个地方就都可以访问了
methodmethod=obj.getclass().getdeclaredmethod("hide",null);
method.invoke(obj,null);
}
catch(exceptione)
{
}

上面的代码已经很完美地实现了通过代码控制toast信息提示框显示和关闭的功能。但如果想实现得更完美,可以在androidsdk源代码中找一个叫itransientnotification.aidl的文件(该文件是aidl服务定义文件,将在后面详细介绍),并在android工程的src目录中建一个android.app包,将这个文件放到这个包中。然后adt会自动在gen目录中生成了一个android.app包,包中有一个itransientnotification.java文件。由于androidsdk自带的itransientnotification接口属于内部资源,外部程序无法访问,因此,只能将从toast对象中获得的mtn变量转换成刚才生成的itransientnotification对象了。这样就不需要使反射技术获得show和hide方法了。经过改良的显示和关闭toast信息提示框的代码如下:
复制代码 代码如下:

itransientnotificationnotification=(itransientnotification)field.get(toast);
//显示toast信息提示框
notification.show();
//关闭toast信息提示框
notification.hide();

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网