43

我有几个SeekBarand onSeekBarProgressStop(),我想显示一条Toast消息。

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

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

我通过使用runOnUIThread()和创建新的Handler.

4

10 回答 10

63

我已经尝试了很多方法来做到这一点。起初我尝试使用cancel(),这对我没有影响(另见这个答案)。

setDuration(n)也不会去任何地方。记录getDuration()结果表明它的值为 0(如果makeText()'s 参数是Toast.LENGTH_SHORT)或 1(如果makeText()'s 参数是Toast.LENGTH_LONG)。

最后,我尝试检查 toast 的 view 是否isShown()。当然,如果没有显示 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
    }
于 2012-07-11T21:25:34.230 回答
42

以下是最受欢迎的答案的替代解决方案,没有 try/catch。

public void showAToast (String message){
        if (mToast != null) {
            mToast.cancel();
        }
        mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
        mToast.show();
}
于 2015-04-11T03:43:58.460 回答
4

开箱即用的干净解决方案。在您的活动中定义:

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);
}
于 2017-06-21T15:29:42.037 回答
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_SHORT未定义LENGTH_LONG,但在实践中效果很好。与其他解决方案相比,它的优势在于您不需要保留 Toast 对象,并且调用语法保持简洁。

于 2012-08-27T19:06:20.163 回答
2

来自上述线程的增强功能,仅在同一短信不可见时才会显示吐司:

 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();
        }

    }
于 2016-07-21T08:32:36.160 回答
1

组合解决方案

对于我的情况,如果显示当前的 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 自定义外观。

于 2017-02-27T10:51:23.840 回答
1

我的解决方案是:

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;
    }

}

有一个这样的助手类。

于 2019-06-27T04:23:29.123 回答
0

适合停止堆叠,例如点击驱动吐司。基于@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)
    {}
}
于 2015-06-13T15:47:55.760 回答
0

检查是否在屏幕上显示 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();
    }
}

}

我希望这个解决方案能帮助你。

谢谢

于 2018-02-22T08:15:54.497 回答
0

添加了计时器以在 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");
于 2018-09-20T09:44:47.527 回答