57

How do I remove all toast messages currently displayed?

In my App, there is a list, when a user clicks on an item, a toast message is displayed, 10 items - 10 toast messages.

So if the user clicks 10 times, then presses the menu button, they have to wait for some seconds until they're able to read the menu option text.

It shouldn't be like that :)

marienke
  • 2,465
  • 4
  • 34
  • 66
crazyV
  • 571
  • 1
  • 4
  • 3
  • Possible duplicate of [Android cancel Toast when exiting the app and when toast is being shown](http://stackoverflow.com/questions/16098151/android-cancel-toast-when-exiting-the-app-and-when-toast-is-being-shown) – Richard Le Mesurier Aug 16 '16 at 21:02
  • Another option: https://stackoverflow.com/a/16103514 – Pavel Mar 23 '18 at 23:36

17 Answers17

83

My solution was to initialize a single Toast in the activity. Then changing its text on each click.

Toast mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
if (a) {
  mToast.setText("This is a");
  mToast.show();
} else if (b) {
  mToast.setText("This is b");
  mToast.show();
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Mudar
  • 1,705
  • 13
  • 16
  • 2
    thanks for your answer, CommonsWare above already explained to disable a list of queued toast messages... :) thx, but sry.. i think u misunderstood the question! – cV2 Dec 21 '10 at 09:18
  • 2
    Although this is a good answer, indeed it is not actually the same behavior. With this solution, you can't ever have two toasts that are showing after each other. – Simon Forsberg Jul 16 '13 at 19:08
32

how do I disable all toast messages being process currently?

You can cancel individual Toasts by calling cancel() on the Toast object. AFAIK, there is no way for you to cancel all outstanding Toasts, though.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • hmm, thanks a lot, will try to create something. but if i add all toast messages to some kind of structure... is there a possibility to check which ones have been shown and which not. I'm kind of busy meanwhile... sry to ask and not to try, at least i'll respond with trying to build something (at the latest) at the end of the week. -thanks!- – crazyV May 03 '10 at 05:14
  • 8
    This is my latest Android pet peeve: no ability to cancel all queued Toasts. – Cody Caughlan Sep 08 '10 at 20:48
  • 3
    What a disappointment: if you cancel the current toast, subsequent toasts will be displayed only after amount of time this toast was about to show. – Pavel Alexeev Sep 16 '14 at 12:11
13

What about checking if a toast is already being displayed?

private Toast toast;
...
void showToast() {
   if (toast == null || toast.getView().getWindowVisibility() != View.VISIBLE) {
      toast = Toast.makeText(getActivity(), "Toast!", Toast.LENGTH_LONG);
      toast.show();
   }
}
Justin Muller
  • 1,283
  • 13
  • 21
  • This worked best for me as I had a pair of Sliders that could each generate several Toasts per second when the user was playing with them. Upvoting with thanks for your contribution. – pete Jul 28 '17 at 18:19
8

Mudar's solution worked beautifully for me on a similar problem - I had various toasts stacking up in a backlog after multiple button clicks.

One instance of Toast with different setText()s and show()s was the exactly the answer I was looking for - previous message cancelled as soon as a new button is clicked. Spot on

Just for reference, here's what I did...

In OnCreate:

    final Toast myToast = Toast.makeText(getBaseContext(), "", Toast.LENGTH_SHORT);

Within in each OnClick:

myToast.setText(R.string.toast1);
myToast.show();
Hussain
  • 5,552
  • 4
  • 40
  • 50
  • 1
    I'm downvoting this simply because I feel that it doesn't add anything new. It could have been a comment to Mudar's answer instead. – Simon Forsberg Jul 16 '13 at 19:10
8

Kotlin Version via Extension Function

The best way to cancel previously shown Toast and display a new one instantly is to keep a reference to the currently shown Toast to be able to cancel it. So using these extension functions really helps:


ToastUtils.kt

import android.content.Context
import android.widget.Toast
import androidx.annotation.StringRes

/**
 * @author aminography
 */

private var toast: Toast? = null

fun Context.toast(message: CharSequence?) {
    toast?.cancel()
    toast = message?.let { Toast.makeText(this, it, Toast.LENGTH_SHORT) }?.apply { show() }
}

fun Context.longToast(message: CharSequence?) {
    toast?.cancel()
    toast = message?.let { Toast.makeText(this, it, Toast.LENGTH_LONG) }?.apply { show() }
}

fun Context.toast(@StringRes message: Int) {
    toast?.cancel()
    toast = Toast.makeText(this, message, Toast.LENGTH_SHORT).apply { show() }
}

fun Context.longToast(@StringRes message: Int) {
    toast?.cancel()
    toast = Toast.makeText(this, message, Toast.LENGTH_LONG).apply { show() }
}

Usage:

context.toast("Text 1")
context.longToast("Text 2")

context.toast(R.string.text3)
context.longToast(R.string.text4)
aminography
  • 21,986
  • 13
  • 70
  • 74
5

My solution is to save all toast references in a list and make a method to cancel all them when need it:

private ArrayList<Toast> msjsToast = new ArrayList<Toast>();

private void killAllToast(){
    for(Toast t:msjsToast){
        if(t!=null) {
            t.cancel();
        }
    }
    msjsToast.clear();
}

When you create a Toast do this way and save the reference:

Toast t = Toast.makeText(context, "Download error: xx", Toast.LENGTH_LONG);
t.show();
msjsToast.addToast(t);

When you need to delete them:

killAllToast();

You can create this like a static method in a global class and use it to kill all the toast of the app.

Viker
  • 3,183
  • 2
  • 25
  • 25
5

Here is my simple answer to the problem:

First in your activity create a global Toast object.

    private Toast example;

Now whenever you want to call a new Toast message just do this:

if(buttonClicked) {
    example.cancel();
    example = Toast.makeText(this, "" , Toast.LENGTH_SHORT);
    example.setText("Button Clicked");
    example.show();
}

This keeps all the Toasts in one central Toast and removes Toast spam. This is a quick rough solution so maybe there is a more elegant way to do it.

Foobar
  • 7,458
  • 16
  • 81
  • 161
4

Create a Toast object outside onClick function and use the code below. It will stop any existing Toast and start the latest Toast.

Toast mToast;

public void onClick(String abc) {

    if(mToast!=null)
        mToast.cancel();
    Context context = this;
    mToast = Toast.makeText(context, abc, Toast.LENGTH_SHORT);
    mToast.show();
}
Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
3

I think I found a way to make toasts message not queue up for me. Thought I would share.

this part goes at top.

private Toast msg;    

This part goes in my setOnTouchListener()

if(null == msg)
{
msg = Toast.makeText("Message to user!", Toast.LENGTH_SHORT);
msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
msg.show();

//handels the stupid queueing toast messages
new Handler().postDelayed(new Runnable()
{
      public void run()
      {
          msg = null;

      }
}, 2000);

}

It is more of a hack than anything. But I show a toast message any time someone favorites a part of my app. And if they go crazy clicking the favorite button it will go crazy with the toasts messages. But not anymore. It will wait 2 seconds and then set my toast object to null and allow it to display again.

S.A.Jay
  • 421
  • 2
  • 9
  • 23
1

This is how I do it.

Toast toast;   

if(toast==null)
        toast=Toast.makeText(getApplicationContext(),R.string.act_now_private_post_text,Toast.LENGTH_LONG);
        else
            toast.setText(R.string.act_now_private_post_text);
        toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL,10,10);
        toast.show();
Victor Odiah
  • 1,061
  • 11
  • 14
1

In my app, queued toasts appearing again and again when app goes into background so I did following to solve the problem.

Add code to detect when app goes into background. One way to register life cycle handler. For More detail ref

registerActivityLifecycleCallbacks(new MyLifecycleHandler());

App.inBackground = true; when app goes to background and show toast using SmartToast class

public class SmartToast {

    static ArrayList<WeakReference<Toast>> toasts = new ArrayList<>();
    public static void showToast(@NonNull Context context,@NonNull String message){
        //this will not allowed to show toast when app in background
        if(App.inBackground) return;
        Toast toast = Toast.makeText(context,message,Toast.LENGTH_SHORT);
        toasts.add(new WeakReference<>(toast));
        toast.show();

        //clean up WeakReference objects itself
        ArrayList<WeakReference<Toast>> nullToasts = new ArrayList<>();
        for (WeakReference<Toast> weakToast : toasts) {
            if(weakToast.get() == null) nullToasts.add(weakToast);
        }
        toasts.remove(nullToasts);
    }

    public static void cancelAll(){
        for (WeakReference<Toast> weakToast : toasts) {
            if(weakToast.get() != null) weakToast.get().cancel();
        }
        toasts.clear();
    }

}

call SmartToast.cancelAll(); method when app goes into background to hide current and all pending toasts. Code is fun. Enjoy!

Community
  • 1
  • 1
Qamar
  • 4,959
  • 1
  • 30
  • 49
1

In Kotlin, it's an easy fix.

In my example, i toggle the sort type when the user clicks on a button. If the user rapidly clicks on the button, it will cancel the currently displayed sortToast before another is shown.

private var sortToast: Toast? = null

sortButton.onClickListener {
    sortToast?.cancel()
    sortToast = Toast.makeText(context, "Sort by toggled", Toast.LENGTH_SHORT)
    sortToast?.show()
}
James
  • 4,573
  • 29
  • 32
0

You can use like this..

class MyToast {
private static Toast t;

public MyToast(Context ctx, String message) {
    if (t != null) {
        t.cancel();
        t = null;
    }
    t = Toast.makeText(ctx, message, Toast.LENGTH_SHORT);
}

public void show() {
    t.show();
}
}
  • 2
    Welcome to SO & Thanks for sharing. Try to add some descriptive text to your code-only answer. ["How do I write a good answer?"](http://stackoverflow.com/help/how-to-answer). _Brevity is acceptable, but fuller explanations are better._ – Scott Solmer Jul 26 '14 at 16:20
0

Using Madur's excellent answer above, I extended this into a class that would deal with different types of messages:

public class ToastManager {
    private Toast toastWarningMessage;
    private Toast toastAddMessage;
    ...

    public void messageWarning(Context context, String message) {
        if(toastWarningMessage == null) {
            toastWarningMessage = Toast.makeText(context, message, Toast.LENGTH_SHORT);
        } else {
            toastWarningMessage.cancel();
            toastWarningMessage.setText(message);
        }
        toastWarningMessage.show();
    }

    public void messageAdd(Context context, String message) {
        if(toastAddMessage == null) {
            toastAddMessage = Toast.makeText(context, message, Toast.LENGTH_SHORT);
        } else {
            toastAddMessage.cancel();
            toastAddMessage.setText(message);
        }
        toastAddMessage.show();
    }
    ...
}

And this is called from within my main activity:

ToastManager toastManager;
...
private void toastWarningMessage(String message) {
    if(toastManager == null) toastManager = new ToastManager();
    toastManager.messageWarning(this, message);
}

The reason for classifying the messages is to make sure that no important messages are overwritten. This solution seems easy to reuse as it only involves renaming the Toasts and the function names.

When the user spams the button, the toast will just cancel each time for the same message type. The only problem is if the user can spam a mix of messages. This leads to the first message repeating and once it finally expires the other messages showing once each. Not really a huge problem, but something to be aware of.

I haven't looked into possible downsides of having multiple Toast instances.

David
  • 1,050
  • 1
  • 16
  • 31
0

How about these !?

private Toast toast;

...
// Methods for short toast messages and long toast messages

    private void showShortToast(String message) {
        if(null != toast) toast.cancel();
        (toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT)).show();
    }

    private void showLongToast(String message) {
        if(null != toast) toast.cancel();
        (toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG)).show();
    }

and at onPause()

@Override
    protected void onPause() {
...
if(null != toast) toast.cancel();
..
}
0
mToast=Toast.makeText(this, "", Toast.LENGTH_LONG);
        showToast.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {

                mToast.cancel();
                String text=null;
                if(ON)
                {
                    text="Toast is on";
                }
                else
                {
                    text="Toast is off";
                }
                mToast.setText(text);
                mToast.setDuration(Toast.LENGTH_SHORT);
                mToast.show();

            }
        });
Adinia
  • 3,722
  • 5
  • 40
  • 58
balu
  • 9
  • 1
-11

Here's how to disable toast messages, remove show() expression.

//Disable notification message
Toast.makeText(this,"Message",Toast.LENGTH_SHORT); 

//Enable notification message
Toast.makeText(this,"Message",Toast.LENGTH_SHORT).show();
Matt
  • 74,352
  • 26
  • 153
  • 180
SKf
  • 137
  • 1
  • 2