Android Toast Custom Display Time

  • 2021-10-13 08:41:55
  • OfStack

Toast is a pop-up prompt method frequently used in Android, which is simple and convenient to use. The conventional usage method is not explained here. Following the previous blog "Toast Full Screen Display in Android", which gives a simple method to realize Toast full screen display, it is found that the display time of Toast cannot be controlled. Although there is an setDuration (int duration) interface in Toast, the tracing code found that the set time didn't work, only the system default two times LENGTH_DURATION = 3500 milliseconds and SHORT_DURATION = 2000 milliseconds. That is to say, no matter how long we set it, only Toast.LENGTH_LONG and Toast.LENGTH_SHORT will ultimately affect the pop-up time of Toast.

At present, there are two main methods to solve this problem:

1. Using reflection principle, control the display time by controlling show () and hide () interfaces of Toast. See blog "Using reflection mechanism to control the display time of Toast". However, this method is only effective for systems below Android 4.0, and it is also true through simulator measurement. The current system is basically above Android4.0, and this method is too old.

2. Use addView () method of WindowManager to swipe the screen dynamically, and you can see the blog "Android customizes Toast, and you can set the display time". This method is used by many software to display floating windows and dynamic floating effects of pictures, such as 360 mobile phone software and 1 mobile game software. It is a good choice on Android 4.0. Of course, this may not work for mobile phones whose system turns off the floating window function by default.

By analyzing the display principle and pop-up control logic of Toast, I successfully realized the arbitrary customization of Toast display time with the help of Handler and Runnable mechanism. The code is modified on the basis of Toast full-screen display and posted as follows:


package com.dls.nltest;
 
import android.content.Context;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.LinearLayout.LayoutParams;
 
public class GenericToast{
 private static final String TAG = "GenericToast";
 
 private static final int TOAST_TEXTSIZE = 20;
 
 /** {@link Toast#LENGTH_SHORT} default time is 3500ms */
 private static final int LENGTH_SHORT_TIME = 2000;
 
 private static Context mContext = null;
 
 private static Toast mToast = null;
 private static TextView mTextView = null;
 private static int mDuration = 0;
 private static CharSequence mText = null;
 
 private Handler mHandler = new Handler();
 
 private GenericToast(Context context) {
 mContext = context;
 }
 
 public static GenericToast makeText(Context context, CharSequence text, int duration){
 GenericToast instance = new GenericToast(context);
 mContext = context;
 mDuration = duration;
 mText = text;
 return instance;
 }
 
 private static void getToast(Context context, CharSequence text){
 mToast = Toast.makeText(context, null, Toast.LENGTH_LONG);
 mToast.setGravity(Gravity.CENTER, 0, 0);
 LinearLayout toastView = (LinearLayout)mToast.getView();
 
 // Get the screen size with unit pixels.
 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
 DisplayMetrics outMetrics = new DisplayMetrics();
 wm.getDefaultDisplay().getMetrics(outMetrics);
 
 mTextView = new TextView(context);
 LayoutParams vlp = new LayoutParams(outMetrics.widthPixels,
        outMetrics.heightPixels); 
 vlp.setMargins(0, 0, 0, 0);
 mTextView.setLayoutParams(vlp);
 mTextView.setTextSize(TOAST_TEXTSIZE);
 mTextView.setText(text);
 mTextView.setGravity(Gravity.CENTER);
 toastView.addView(mTextView);
 }
 
 /**
 * Before call this method, you should call {@link makeText}.
 *
 * @return Toast display duration.
 */
 public int getDuration(){
 return mDuration;
 }
 
 public void show(){
 Log.d(TAG, "Show custom toast");
 mHandler.post(showRunnable);
 }
 
 public void hide(){
 Log.d(TAG, "Hide custom toast");
 mDuration = 0;
 if(mToast != null){
 mToast.cancel();
 }
 }
 
 private Runnable showRunnable = new Runnable(){
 @Override
 public void run() {
 if(mToast != null){
 mTextView.setText(mText);
 }else{
 getToast(mContext, mText);
 }
 if(mDuration != 0){
 mToast.show();
 }else{
 Log.d(TAG, "Hide custom toast in runnable");
 hide();
 return;
 }
 
 if(mDuration > LENGTH_SHORT_TIME){
 mHandler.postDelayed(showRunnable, LENGTH_SHORT_TIME);
 mDuration -= LENGTH_SHORT_TIME;
 }else{
 mHandler.postDelayed(showRunnable, mDuration);
 mDuration = 0;
 }
 }
 };
}

Toast pop-up window 10s, test code is as follows:


GenericToast mGToast = GenericToast.makeText(this, "I am generic toast", 10 * 1000);
mGToast.show();

If you need to terminate the pop-up window, just call hide () where you need it.


Related articles: