如何取消Toast

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何取消Toast相关的知识,希望对你有一定的参考价值。

我遇到了一个关于Toast的问题假设我的Toast显示在程序的窗口中,当Dialog box出现的时候,它不能立即消失,请问如何取消Toast.

参考技术A Toast默认显示时间参数有两种,0是比较短的,1是比较长的,如果要代码控制消失,直接调用Toast的cancel()就可以了,这个方法是说如果Toast还在显示就关闭Toast,你试试
查看原帖>>

如果已经显示了一个 Toast,如何避免 Toast

【中文标题】如果已经显示了一个 Toast,如何避免 Toast【英文标题】:How to avoid a Toast if there's one Toast already being shown 【发布时间】:2011-10-19 00:05:03 【问题描述】:

我有几个SeekBaronSeekBarProgressStop(),我想显示一个Toast 消息。

但如果在SeekBar 上我快速执行操作,那么 UI 线程会以某种方式阻塞,Toast 消息会等待直到 UI 线程空闲。

现在我担心的是,如果 Toast 消息已经显示,则要避免新的 Toast 消息。或者他们是我们检查 UI 线程当前空闲的任何条件,然后我将显示 Toast 消息。

我尝试了两种方式,使用runOnUIThread() 并创建新的Handler

【问题讨论】:

【参考方案1】:

我已经尝试了很多方法来做到这一点。起初我尝试使用cancel(),但对我没有效果(另请参阅this answer)。

setDuration(n) 我也不会去任何地方。通过记录 getDuration() 发现它的值为 0(如果 makeText() 的参数是 Toast.LENGTH_SHORT)或 1(如果 makeText() 的参数是 Toast.LENGTH_LONG)。

最后我尝试检查吐司的视图isShown()。当然,如果没有显示 toast 则不是,但更重要的是,在这种情况下它会返回一个致命错误。所以我需要尝试捕捉错误。 现在,如果显示 toast,isShown() 返回 true。 利用isShown()我想出了方法:

    /**
     * <strong>public void showAToast (String st)</strong></br>
     * this little method displays a toast on the screen.</br>
     * it checks if a toast is currently visible</br>
     * if so </br>
     * ... it "sets" the new text</br>
     * else</br>
     * ... it "makes" the new text</br>
     * and "shows" either or  
     * @param st the string to be toasted
     */

    public void showAToast (String st) //"Toast toast" is declared in the class
        try toast.getView().isShown();     // true if visible
            toast.setText(st);
         catch (Exception e)          // invisible if exception
            toast = Toast.makeText(theContext, st, toastDuration);
            
        toast.show();  //finally display it
    

【讨论】:

好答案。一句话: isShown() “引发异常”的原因是 toast.getView() 最初返回null。简单地测试 null 而不是使用 try...catch。 您可以考虑直接检查而不是尝试/捕获,因为这是预期的常见情况。 查看我的回答 (***.com/a/29573861/2457744),了解如何在不尝试/捕获的情况下进行操作。 当我使用 Toast.LENGTH_SHORT 时它不工作,使用 Toast.LENGTH_LONG 工作正常后。 Toast.getView() 在 Android 11+ (***.com/questions/62884286/…) 上总是返回 null,所以这个解决方案已经过时了【参考方案2】:

记录您上次展示 toast 的时间,如果它在某个时间间隔内,则重新展示它。

public class RepeatSafeToast 

    private static final int DURATION = 4000;

    private static final Map<Object, Long> lastShown = new HashMap<Object, Long>();

    private static boolean isRecent(Object obj) 
        Long last = lastShown.get(obj);
        if (last == null) 
            return false;
        
        long now = System.currentTimeMillis();
        if (last + DURATION < now) 
            return false;
        
        return true;
    

    public static synchronized void show(Context context, int resId) 
        if (isRecent(resId)) 
            return;
        
        Toast.makeText(context, resId, Toast.LENGTH_LONG).show();
        lastShown.put(resId, System.currentTimeMillis());
    

    public static synchronized void show(Context context, String msg) 
        if (isRecent(msg)) 
            return;
        
        Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
        lastShown.put(msg, System.currentTimeMillis());
    

然后,

RepeatSafeToast.show(this, "Hello, toast.");
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown
RepeatSafeToast.show(this, "Hello, toast."); // won't be shown

这并不完美,因为 LENGTH_SHORTLENGTH_LONG 的长度未定义,但在实践中效果很好。与其他解决方案相比,它的优势在于您不需要保留 Toast 对象,并且调用语法保持简洁。

【讨论】:

很好,正是我想要的。效果很好。 也许是个好主意,但没有完美实现。您将对象放入 HashMap 中,但不删除它们。 由于键是要烘烤的字符串,因此映射的大小受要烘烤的字符串数量的限制。仅当您正在烘烤动态字符串(“foo bar”+ i)时,您的观点才有效。如果您需要更好的,请将 HashMap 替换为 LruCache。【参考方案3】:

以下是most popular answer 的替代解决方案,不带try/catch。

public void showAToast (String message)
        if (mToast != null) 
            mToast.cancel();
        
        mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
        mToast.show();

【讨论】:

最好的,谢谢!【参考方案4】:

适用于停止堆叠,例如点击驱动吐司。基于@Addi 的回答。

public Toast toast = null;
//....
public void favsDisplay(MenuItem item)

    if(toast == null) // first time around
    
        Context context = getApplicationContext();
        CharSequence text = "Some text...";
        int duration = Toast.LENGTH_SHORT;
        toast = Toast.makeText(context, text, duration);
    
    try
    
        if(toast.getView().isShown() == false) // if false not showing anymore, then show it
            toast.show();
    
    catch (Exception e)
    

【讨论】:

【参考方案5】:

上述线程的增强功能,仅当与相同的文本消息不可见时才会显示吐司:

 public void showSingleToast()
        try
            if(!toast.getView().isShown())     
                toast.show();
            
         catch (Exception exception) 
            exception.printStackTrace();       
            Log.d(TAG,"Toast Exception is "+exception.getLocalizedMessage());
            toast = Toast.makeText(this.getActivity(),   getContext().getString(R.string.no_search_result_fou`enter code here`nd), Toast.LENGTH_SHORT);
            toast.show();
        

    

【讨论】:

【参考方案6】:

综合解决方案

就我而言,如果显示当前的 toast,我需要取消它并显示另一个。

这是为了解决当用户在服务仍在加载或不可用时请求服务的情况,我需要展示一个 toast(如果请求的服务不同,我可能会有所不同)。否则,toast 会一直按顺序显示,并且需要很长时间才能自动隐藏。

所以基本上我保存了正在创建的 toast 的实例,下面的代码是如何安全地取消它

synchronized public void cancel() 
    if(toast == null) 
        Log.d(TAG, "cancel: toast is null (occurs first time only)" );
        return;
    
    final View view = toast.getView();
    if(view == null)
        Log.d(TAG, "cancel: view is null");
        return;
    
    if (view.isShown()) 
        toast.cancel();
    else
        Log.d(TAG, "cancel: view is already dismissed");
    

为了使用它,我现在不用担心取消,如下所示:

if (toastSingleton != null ) 
    toastSingleton.cancel();
    toastSingleton.showToast(messageText);
else
    Log.e(TAG, "setMessageText: toastSingleton is null");

showToast 由您决定如何实现它,因为我需要自定义的 toast 外观。

【讨论】:

真实逻辑和真实检查空视图,然后再检查是否显示。多次调用显示祝酒词是一种很长很奇怪的体验,尤其是在用户已经退出应用程序的情况下。如您所述,必须取消当前然后调用新的。谢谢。【参考方案7】:

开箱即用的干净解决方案。在你的 Activity 上定义这个:

private Toast toast;

/**
 * Use this to prevent multiple Toasts from spamming the UI for a long time.
 */
public void showToast(CharSequence text, int duration)

    if (toast == null)
        toast = Toast.makeText(this, text, duration);
    else
        toast.setText(text);
    toast.show();


public void showToast(int resId, int duration)

    showToast(getResources().getText(resId), duration);

【讨论】:

【参考方案8】:

检查是否在屏幕上显示 toast 消息,无论它是否显示。 用于显示 toast 消息创建一个单独的类。并使用此类在检查 toast 消息的可见性后显示 toast 消息的方法。使用这段代码:

public class AppToast 

private static Toast toast;

public static void showToast(Context context, String message) 
    try 
        if (!toast.getView().isShown()) 
            toast=Toast.makeText(context, message, Toast.LENGTH_SHORT);
            toast.show();
        
     catch (Exception ex) 
        toast=Toast.makeText(context,message,Toast.LENGTH_SHORT);
        toast.show();
    



我希望这个解决方案对你有所帮助。

谢谢

【讨论】:

【参考方案9】:

添加了 2 秒后移除吐司的计时器。

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");

【讨论】:

【参考方案10】:

我的解决办法是:

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;
    

并且调用者应该有这个方法参数的 Toast 成员,或者

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;
    


有一个这样的辅助类。

【讨论】:

我找到了同样的解决方案。如果 isShown() 没有按预期工作,那么就不要使用它:) 如果它不为空,则取消() toast。

以上是关于如何取消Toast的主要内容,如果未能解决你的问题,请参考以下文章

更改片段后如何取消显示堆叠的吐司?

在特定时间取消重复警报

android - 将toast从一个活动传递到另一个活动

连接/断开 USB BroadcastReceiver 时隐藏/取消隐藏应用程序

Toast分析——实现自己的Toast

android怎么缩短toast的显示时间