http://blog.sina.com.cn/s/blog_76264a170100tfn7.html
Android的Toast是一个很常用的消息提示组件,开发的时候一般是用
Toast
.
makeText(
context
,
text
,
duration
).
show();
来显示一条toast。这种方法有一个问题,如果一条旧消息没有消失以前,又产生了一条新消息,这时候新消息必须等待旧消息消失才能出现。然而实际情况中,我们通常更期望的表现是旧消息马上中止,新消息立刻出现。(不及时的通知不是好通知)
那么怎样才能达到这种效果呢?
Toast.makeText是一个静态工厂方法,每次调用这个方法都会产生一个新的Toast对象,在这个对象上调用show方法就会使这个对象加入到消息显示的队列里排队等候显示。实际上,如果我们不每次都产生一个新的toast对象,而是每一次都是用同一个,那么就不需要排队了,我们要的及时更新效果也就可以实现了。
实际上,我们可以使用Toast本身的构造器产生一个新的Toast对象,并用setText和setDuration方法来达到和makeText同样的设置,之后也一样用show方法来显示。这样就把makeText方法产生对象和设置属性的操作分开来进行。也就是说,我们显示下一个toast的时候,可以不必再产生新对象,只要在原来的对象上重新设置属性,并重新show就可以了,这样新的toast就会代替原来的马上显示。
代码大概是这样:
t
=
new
Toast(
context);
t . setText( text);
t . setDuration( duration);
t . show();
t . setText( text_new);
t . setDuration( duration_new);
t . show();
t . setText( text);
t . setDuration( duration);
t . show();
t . setText( text_new);
t . setDuration( duration_new);
t . show();
但实际上你会发现这个代码运行会报错,看看log就明白,说是必须调用setView方法。这个setView方法,是用来设置toast显示的view的,也就是说,我们可以让toast显示在自定义的view里,而不是那个统一的黑框里(除非特殊用途,一般不推荐,用户体验的统一是王道)。makeText这个方法是默认用那个统一黑框布局的(com.android.internal.R.layout.transient_notification),但通过构造器构造出来的toast必须自己手动设置setView。最要命的是默认的黑框布局在com.android.internal这个包里,而这个包在开发环境是访问不到的。
这可怎么办呢?难道只能自定义一个view么?或者从android源码里把这个layout抓出来?前者毁坏了用户体验,后者也有问题,比如不同机器的移植layout是不同的。好在除了setView,toast还提供了一个对应的方法叫getView,我们可以通过makeText创建一个默认布局的toast然后通过getView拿到它的View的引用保存起来,以后每次产生toast的时候都使用这同一个View就好了。
可以正常运行的代码如下:
t
=
new
Toast(
context);
View v = Toast . makeText( context , "" , Toast . LENGTH_SHORT ). getView();
t . setView( v);
t . setText( text);
t . setDuration( duration);
t . show();
t . setText( text_new);
t . setDuration( duration_new);
t . show();
View v = Toast . makeText( context , "" , Toast . LENGTH_SHORT ). getView();
t . setView( v);
t . setText( text);
t . setDuration( duration);
t . show();
t . setText( text_new);
t . setDuration( duration_new);
t . show();
以上是概念代码,实际应用中,我们可以在应用的全局环境类里(通常是一个singleton)实现一个toast管理器的singleton,这样就确保所有的toast都通过这一个view来显示。至于toast管理器的单例实现,用一个enum就可以了,示例代码如下:
public
enum
toastMgr
{
builder;
private
View
v;
private
Toast
it;
private
void
init(
Context
c)
{
LayoutInflater
inflate
=(
LayoutInflater)
c
.
getSystemService(
Context
.
LAYOUT_INFLATER_SERVICE);
v
=
Toast
.
makeText(
c
,
""
,
Toast
.
LENGTH_SHORT
).
getView();
it
=
new
Toast(
c);
it
.
setView(
v);
}
public
void
display(
CharSequence
text
,
int
duration)
{
it
.
setText(
text);
it
.
setDuration(
duration);
it
.
show();
}
public
void
display(
int
Resid
,
int
duration)
{
it
.
setText(
Resid);
it
.
setDuration(
duration);
it
.
show();
}
}
}