18

In Android, when I create Toast and show them, they appear consecutively. The problem is that I have a button that checks some fields and if the user enters incorrect data, a Toast is shown. If the user touches the button repeatedly, Toasts are accumulated and the message does not disappear for a couple of seconds.

Which is the best way to avoid that?

  • May I save the reference to the last Toast and remove it before making a new one?
  • Should I use the same Toast for all messages?
  • Might I use any method that clears all the Application Toasts before making and showing the new one?
Didac Perez Parera
  • 3,734
  • 3
  • 52
  • 87
  • i have the same problem, i share you few ideas that haven't worked, making toast final, using if conditions also, using counters.. :\ i will watch this question now. – Rachit Mishra Sep 07 '13 at 18:25
  • 2
    Hola(Hello) Didac, have you tried [this](http://stackoverflow.com/questions/12922516/how-to-prevent-multiple-toast-overlaps) or [that](http://stackoverflow.com/questions/6496725/showing-multiple-toast-at-the-same-time-problem) ? – AlexBcn Sep 07 '13 at 18:27
  • The best way is to not use Toasts. :) might – Kevin Coppock Sep 07 '13 at 18:34

4 Answers4

41

You can use the cancel() method of Toast to close a showing Toast.

Use a variable to keep a reference to every Toast as you show it, and simply call cancel() before showing another one.

private Toast mToast = null; // <-- keep this in your Activity or even in a custom Application class

//... show one Toast
if (mToast != null) mToast.cancel();
mToast = Toast.makeText(context, text, duration);
mToast.show();

//... show another Toast
if (mToast != null) mToast.cancel();
mToast = Toast.makeText(context, text, duration);
mToast.show();

// and so on.

You could even wrap that into a small class like so:

public class SingleToast {

    private static Toast mToast;

    public static void show(Context context, String text, int duration) {
        if (mToast != null) mToast.cancel();
        mToast = Toast.makeText(context, text, duration);
        mToast.show();
    }
}

and use it in your code like so:

SingleToast.show(this, "Hello World", Toast.LENGTH_LONG);

//

Didac Perez Parera
  • 3,734
  • 3
  • 52
  • 87
Ridcully
  • 23,362
  • 7
  • 71
  • 86
  • 5
    The `SingleToast` solution works, but it has a memory issue. It retains `context` for the lifetime of `mToast` which can way exceed the would-be lifetime of `context`. One should use `context.getApplicationContext()` instead to avoid a memory leak. – Aleks N. Oct 26 '16 at 14:07
1

Have only one Toast in this activity.

private Toast toast = null;

Then just check if there's currently a Toast being shown before creating another one.

if (toast == null || !toast.getView().isShown()) {
    if (toast != null) {
        toast.cancel();
    }
    toast = Toast.makeToast("Your text", Toast.LENGTH).show();
}

You can even make that last snippet into a private method showToast(text) to refactor code if you need to display different text messages.

Juan Andrés Diana
  • 2,215
  • 3
  • 25
  • 36
1

In Kotlin I use this:

private lateinit var toast: Toast

fun showToast(@StringRes stringId: Int, toastLength: Int = Toast.LENGTH_SHORT)
{
    if (this::toast.isInitialized)
    {
        toast.cancel()
    }

    toast = Toast.makeText(
        requireContext(),
        getString(stringId),
        toastLength
    )

    toast.show()
}

Or when using it in many fragments it is possible to extend the Fragment class, so function showToast doesn't have to be in every fragment.

open class OneToastFragment : Fragment()
{
    private lateinit var toast: Toast

    fun showToast(@StringRes stringId: Int, toastLength: Int = Toast.LENGTH_SHORT)
    {
        if (this::toast.isInitialized)
        {
            toast.cancel()
        }

        toast = Toast.makeText(
            requireContext(),
            getString(stringId),
            toastLength
        )

        toast.show()
    }
}

Also, it can be easy using Toasty library.

Gradle project:

repositories {
    ...
    maven { url "https://jitpack.io" }
}

Gradle module app:

dependencies {
    ...
    implementation 'com.github.GrenderG:Toasty:1.4.2'
}

onCreate in Activity class:

Toasty.Config.getInstance().allowQueue(false).apply(); // set this to avoid toast acumulations

//Test:
int x = 0;
Toasty.info(this, Integer.toString(x++), Toast.LENGTH_SHORT, true).show();
Toasty.info(this, Integer.toString(x++), Toast.LENGTH_SHORT, true).show();
Toasty.info(this, Integer.toString(x++), Toast.LENGTH_SHORT, true).show();

//This will only show a toast with message `2` 
iknow
  • 8,358
  • 12
  • 41
  • 68
0

This will only make a new toast after a pre-defined delay (3 seconds in this case) irrespective of how many times the user press that button.

Kotlin

var mLastToastTime: Long = 0
val mNewToastInterval: Int = 3000 // milliseconds

if (System.currentTimeMillis() - mLastToastTime > mNewToastInterval) {
    showToast()
    mLastToastTime = System.currentTimeMillis().toInt()
}

Java

int mLastToastTime = 0;
int mNewToastInterval = 3000; // milliseconds

if (System.currentTimeMillis() - mLastToastTime > mNewToastInterval) {
       showToast();
       mLastToastTime = System.currentTimeMillis();
}
shahrukhamd
  • 259
  • 6
  • 6