How to avoid a Toast if there's one Toast already being shown

Viewed 36967

I have several SeekBar and onSeekBarProgressStop(), I want to show a Toast message.

But if on SeekBar I perform the action rapidly then UI thread somehow blocks and Toast message waits till UI thread is free.

Now my concern is to avoid the new Toast message if the Toast message is already displaying. Or is their any condition by which we check that UI thread is currently free then I'll show the Toast message.

I tried it in both way, by using runOnUIThread() and also creating new Handler.

11 Answers

My solution is:

public class Utils {
    public static Toast showToast(Context context, Toast toast, String str) {
        if (toast != null)
            toast.cancel();
        Toast t = Toast.makeText(context, str, Toast.LENGTH_SHORT);
        t.show();
        return t;
    }
}

and the caller should have a Toast member for this method's parameter, or

class EasyToast {
    Toast toast;
    Context context;

    public EasyToast(Context context) {
        this.context = context;
    }

    public Toast show(String str) {
        if (toast != null)
            toast.cancel();
        Toast t = Toast.makeText(context, str, Toast.LENGTH_SHORT);
        t.show();
        return t;
    }

}

have a helper class like this.

added timer to remove the toast after 2 seconds.

private Toast toast;

public void showToast(String text){
        try {
            toast.getView().isShown();
            toast.setText(text);
        }catch (Exception e){
            toast = Toast.makeText(mContext, text, Toast.LENGTH_SHORT);
        }
        if(toast.getView().isShown()){
            new Timer().schedule(new TimerTask() {
                @Override
                public void run() {
                    toast.cancel();
                }
            }, 2000);
        }else{
            toast.show();
        }
    }

showToast("Please wait");

Solution for Android 11+ (API level 30 and above)

Toast.getView() is deprecated since API level 30:

This method was deprecated in API level 30. Custom toast views are deprecated. Apps can create a standard text toast with the makeText(android.content.Context, java.lang.CharSequence, int) method, or use a Snackbar when in the foreground. Starting from Android Build.VERSION_CODES#R, apps targeting API level Build.VERSION_CODES#R or higher that are in the background will not have custom toast views displayed.

If you want to avoid Toast overlapping, you could save the time the last Toast was shown using System.currentTimeMillis().

Here's a an example of use case where Toast is instantly overlapped only if the text of the new one is different from the last one, otherwise, it waits a certain amount of time before overlapping it (i.e SAME_TOAST_DURATION_BEFORE_OVERLAP):

public class SingleToast {
    private static Toast _toast;
    private static String _text;
    private static long _lastToast;
    private static final int SAME_TOAST_DURATION_BEFORE_OVERLAP = 2000; // in ms

    public static void show(Context context, String text, int duration) {
        if (_toast == null) {
            _toast = Toast.makeText(context.getApplicationContext(), text, duration);
            _text = text;
        } else {
            if (_text.equals(text)) {
                if (System.currentTimeMillis() - _lastToast > SAME_TOAST_DURATION_BEFORE_OVERLAP) {
                    _toast.cancel();
                } else {
                    return;
                }
            } else {
                _text = text;
                _toast.cancel();
                _toast.setText(_text);
            }
        }
        _lastToast = System.currentTimeMillis();
        _toast.show();
    }
}
Related