【问题标题】:Android Toast on top of Toast - bottom one remains when top one goes在 Toast 之上的 Android Toast - 当顶部消失时底部的底部仍然存在
【发布时间】:2019-09-23 17:13:34
【问题描述】:

我的应用程序通过调用在许多地方创建了许多 toasts

Toast.makeText(getBaseContext(), "Blah", Toast.LENGTH_SHORT).show();

(好吧,我使用资源 id 而不是字符串)。在我使用过的从 4 到 7 的每个 Android 版本上一切正常,但在 Android 8.1.0 中,如果在第一个 toast 消失之前弹出第二个 toast,则在第二个解散时恢复第一个 toast。我的猜测是,显示管理器会记住吐司下方的像素,并在吐司消失时恢复它们,但它不够聪明,无法处理一堆吐司,所以第二个“记住”第一个的图像,并恢复它而不是底层的窗口区域。

我可以使用“makeToast”包装器解决这个问题,该包装器每次都将 Toast 对象存储在一个静态变量中,并在 .show() 调用新对象之前在旧对象上调用 .cancel()。这是最终的解决方案,还是有更好的方法?

private static Toast lastToast;
private static Context toastContext; // set in onCreate
public static void makeToast(int resId, int duration) {
    if (lastToast != null) lastToast.cancel();
    lastToast = Toast.makeText(toastContext, resId, duration);
    lastToast.show();
}

【问题讨论】:

  • 我没有得到和你一样的行为......在一个新的安卓应用程序上,如果我一个接一个地运行Toast.makeText(getBaseContext(), "Blah", Toast.LENGTH_SHORT).show(); Toast.makeText(getBaseContext(), "Blah2", Toast.LENGTH_SHORT).show();,第一个被第二个替换
  • 除 8.1.0 外,我还发现了您在每个 android 和每个设备上看到的行为。我确实想知道线程上下文,所以我使用 Handler.post() 将调用推送到主 UI 线程。问题依然存在。仔细观察屏幕,当第二个 toast 消失时,显示会短暂恢复到应有的状态,但随后底层的 toast 消息会以全部强度重新出现,就好像第二个 toast 下的像素抓取突然恢复了一样。奇怪!
  • 这很奇怪...我已经在 android 9 上运行了测试,所以它可能是您使用的特定 android 版本中的一个错误
  • 这个可能性很大!但我真的需要明天让它工作,所以与设备供应商的争论可能不会削减它:-)
  • @Quinn 我完全尝试了您的代码:- Toast.makeText(this, "fu", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "bar", Toast.LENGTH_SHORT).show(); 紧接着一个调用,所以上下文完全相同。 “bar”出现在“fu”之上,当“bar”消失时,“fu”又回来了。绝对是令人兴奋的事情!

标签: android toast android-toast


【解决方案1】:

这为我解决了这个问题 - 我用我自己的类包裹了 Toast,cancel()s 最后一个在 show()ing 新对象之前调用 show() 的对象。看起来像是一个大规模的 hack,但它确实完成了工作,只需要在我的应用程序的其余部分更改 import android.widget.Toast 行。

package my.app.hacks;

import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;    

public class Toast extends android.widget.Toast {
    public static final int LENGTH_SHORT = android.widget.Toast.LENGTH_SHORT;
    public static final int LENGTH_LONG = android.widget.Toast.LENGTH_LONG;

    private static Toast lastShown;

    public Toast(Context context) {
        super(context);
    }

    public void show() {
        if (lastShown != null) lastShown.cancel();
        super.show();
        lastShown = this;
    }

    public static Toast makeText(Context context, CharSequence text, int duration) {
        //
        // this is almost copy-n-pasted from android.widget.Toast.makeText()
        //
        Toast result = new Toast(context);

        LayoutInflater inflate = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        // we can't directly access com.android.internal.R identifiers so use the public interface
        int layout = Resources.getSystem().getIdentifier("transient_notification", "layout", "android");
        View v = inflate.inflate(layout, null);
        int id = Resources.getSystem().getIdentifier("message", "id", "android");
        TextView tv = (TextView)v.findViewById(id);
        tv.setText(text);

        // the original code accesses private members here - again, we have to use the public interface
        result.setView(v);
        result.setDuration(duration);

        return result;
    }

    public static Toast makeText(Context context, int resId, int duration)
            throws Resources.NotFoundException {
        return makeText(context, context.getResources().getText(resId), duration);
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多