Android Toast是一种比较特殊的显示信息的机制,其没有焦点,并且显示一段时间之后就自动消失。Android 中提供的显示时长通过Toast.LENGHT_LONG和Toast.LENGTH_SHORT来指定,底层具体代表的时间长度分别是3.5s和2.0s。
本文介绍如何使得Toast显示的时间更长或者指定显示时间长度。
1. 基本用法代码示例
/** * Toast默认的长时间显示 3.5s */ @OnClick(R.id.one_button) public void onClickOneButton() { Toast.makeText(this, "Hello World", Toast.LENGTH_LONG).show(); } /** * Toast默认的短时间显示 2.0s */ @OnClick(R.id.two_button) public void onClickTwoButton() { Toast.makeText(this, "Hello World", Toast.LENGTH_SHORT).show(); }
2. 通过android.os.CountDownTimer类实现Toast的显示和消失
通过点击下图中的底端左Button使得Toast显示,右Button使得Toast消失。
代码示例:
/** * 使用CountDownTimer实现Toast自定义时间显示 */ @Bind(R.id.three_textView) public TextView threeTextView; private Toast mCountDownTimeToast; public CountDownTimer cdt = new CountDownTimer(60 * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { threeTextView.setText("Time剩余:" + (millisUntilFinished / 1000) + "s"); if (null != mCountDownTimeToast) { mCountDownTimeToast.show(); } } @Override public void onFinish() { threeTextView.setText("显示完成"); if (null != mCountDownTimeToast) { mCountDownTimeToast.cancel(); } } }; @OnClick({R.id.three_button_start, R.id.three_button_cancel}) public void onClickThreeButton(View v) { if (null == mCountDownTimeToast) { mCountDownTimeToast = makeToast(this); mCountDownTimeToast.setGravity(Gravity.TOP | Gravity.LEFT, 30, 30); } if (v.getId() == R.id.three_button_start) { cdt.start(); Log.d(TAG, "CountDownTimer start show"); } if (v.getId() == R.id.three_button_cancel) { cdt.cancel(); threeTextView.setText("取消"); Log.d(TAG, "CountDownTimer cancel"); } }
Toast对象的View布局文件(view_toast.xml)
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ef3939" android:orientation="vertical" style="@android:style/TextAppearance.DeviceDefault.Medium" android:gravity="center_vertical|center_horizontal" android:padding="10dp" android:text=""Hello World"" android:textColor="#f7f9fb"> </TextView>
创建Toast对象(下文中创建Toast对象使用该方法)
public static Toast makeToast(Context context) { Toast toast = new Toast(context); toast.setDuration(Toast.LENGTH_SHORT); TextView view = (TextView) LayoutInflater.from(context).inflate(R.layout.view_toast, null); toast.setView(view); return toast; }
上述代码通过CountDownTimer实现指定Toast显示时长和控制Toast显示与消失,重构之后代码如下:
public void showToast1(final Toast toast, long duration) { final long SHORT = 2000; final long LONG = 3500; final long ONE_SECOND = 1000; final long d = duration <= SHORT ? SHORT : duration > LONG ? duration : LONG; new CountDownTimer(Math.max(d, duration), ONE_SECOND) { @Override public void onTick(long millisUntilFinished) { toast.show(); } @Override public void onFinish() { toast.cancel(); } }.start(); }
3.通过Handler消息机制实现
public void showToast2(final Toast toast, long duration) { final long SHORT = 2000; final long LONG = 3500; final long ONE_SECOND = 1000; final long d = duration <= SHORT ? SHORT : duration > LONG ? duration : LONG; final int what = 1; final Handler handler = new Handler() { long remainder = d; @Override public void handleMessage(Message msg) { if (msg.what == what) { toast.show(); if (remainder >= ONE_SECOND) { remainder -= ONE_SECOND; sendEmptyMessageDelayed(what, ONE_SECOND); } else { removeMessages(what); } } } }; handler.sendEmptyMessage(what); }
其实这种实现和CountDownTimer实现的机制一样的。
4. Toast的指定时长显示其实就是不断的调用Toast的show()方法,其中show()方法中实现了将Toast对象添加到INotificationManager的Toast队列中去。具体细节可参见Toast(android.widget.Toast)源码。
5. 为什么要给Toast指定显示时长呢?
这或许不是个好主意。Toast的无焦点短时间自动消失机制就是为了给用户显示信息而不会产生较大干扰。如果长时间显示并且具有更多交互和事件处理,这就背离了Toast的本意,这样的场景可以考虑使用Notification,Dialog来实现。
使用Toast场景中更多的是关注其View和显示的位置,这可以实现更多有意思的东西,比如冒泡提示,使用向导等。在实践中则需要根据具体情况慎重选择和合理应用。