Snackbar 制作Toast遇到遮挡处理

Snackbar 制作Toast遇到遮挡处理

为什么要用Snackbar替代Toast

Toast If your app targets Android 12 (API level 31) or higher, its toast is limited to two lines of text and shows the application icon next to the text. Be aware that the line length of this text varies by screen size, so it's good to make the text as short as possible. 如果你的应用程序目标是Android 12(API级别31)或更高版本,其Toast仅限于两行文本,并在文本旁边显示应用程序图标。请注意,此文本的行长度因屏幕大小而异,因此最好使文本尽可能短。

If your app is in the foreground, consider using a snackbar instead of using a toast. Snackbars include user-actionable options, which can provide a better app experience.

If your app is in the background, and you want users to take some action, use a notification instead.

如果你的应用程序在前台,可以考虑使用Snackbar而不是Toast。Snackbar包括用户可操作的选项,可以提供更好的应用程序体验。

如果你的应用程序在后台,并且你希望用户采取一些行动,请使用Notification。

Snackbar局限性在于依附view,如何出现dialog或者popwindow等遮挡弹框将会被遮盖在后面。官方提的Notification可以作为后台弹窗,通常顶部弹出,展示效果和Toast存在着差异。另一种是将Snackbar制作成强行显示在应用最上方,需要借助WindowManager,还需要运行时权限申请。

Dialog 辅助 Snackbar制作不被遮挡的Snackbar

  • 定义一个全屏透明的Dialog作为snackbar的容器窗口
  • 给Dialog做一个延迟取消,时常和snackbar长短时长等同
  • 控制窗口透明度,两窗口叠加时透明度会受到影响
  • 页面销毁时要跳出方法不让重新创建
  • Dialog受制于actvity,无法跨页面显示
ini 复制代码
public static void show(final Context context, final String message, final int duration) {
    AppCompatActivity act = ((AppCompatActivity) context);
    if (act.isFinishing()) {
        return;
    }
    if (alertDialog != null && alertDialog.isShowing()) {
        alertDialog.dismiss();
    }
    Window win = act.getWindow();
    View rootView = win.getDecorView(); //activity.findViewById(android.R.id.content);
    alertDialog = new MaterialAlertDialogBuilder(context, R.style.MaterialDialogTheme).create();
    alertDialog.show();
    Window window = alertDialog.getWindow();
    WindowManager.LayoutParams params = window.getAttributes();
    params.width = WindowManager.LayoutParams.MATCH_PARENT;
    params.height = WindowManager.LayoutParams.MATCH_PARENT;
    params.dimAmount = 0.2f;
    window.setAttributes(params);
    window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    rootView.postDelayed(() -> {
        if (act==null||act.isFinishing()) {
            return;
        }
        if (alertDialog != null && alertDialog.isShowing()) {
            alertDialog.dismiss();
        }
    }, duration == Toast.LENGTH_SHORT ? 1500 : 2750);
    show(window.getDecorView(), message, duration);
}
ini 复制代码
public static Snackbar toast(View rootView, String message, int duration) {

    Snackbar mSnackbar =
            Snackbar.make(rootView, "Replace with your own action", duration);
    Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) mSnackbar.getView();
    layout.setBackgroundColor(Color.TRANSPARENT);
    layout.setElevation(0);
    layout.setPadding(0, 0, 0, 0);
    TextView textView =
            layout.findViewById(com.platform.view.R.id.snackbar_text);
    textView.setVisibility(View.GONE);

    View view = LayoutInflater.from(rootView.getContext()).inflate(com.platform.view.R.layout.customer_snackbar_toast, layout);
    AppCompatImageView ivIcon = view.findViewById(com.platform.view.R.id.iv_snack_icon);
    ivIcon.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            ivIcon.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            try {
                ivIcon.setImageResource(rootView.getContext().getApplicationInfo().icon);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    });
    AppCompatTextView tvMessage = view.findViewById(com.platform.view.R.id.tv_snack_message);
    tvMessage.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            tvMessage.setText(message);
            tvMessage.getViewTreeObserver().removeOnGlobalLayoutListener(this);

        }
    });
    FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) view.getLayoutParams();
    param.gravity = Gravity.CENTER;
    mSnackbar.setBackgroundTint(Color.TRANSPARENT);
    return mSnackbar;
}

具体更换Toast方案看自己使用场景

相关推荐
问心无愧051316 分钟前
ctf show web入门109
android·前端·笔记
xinhuanjieyi35 分钟前
Android 画板应用kotlin实现
android·开发语言·kotlin
故渊at1 小时前
第四板块:Android 输入系统与触控事件 | 第十六篇:按键分发与软键盘(IME)的窗口协同
android·软键盘·输入系统·触控事件·按键分发
故渊at1 小时前
第三板块:Android 图形渲染与窗口体系 | 第十四篇:View 绘制体系与 RenderThread 异步渲染
android·图形渲染·ui线程·renderthread·view体系
Coffeeee1 小时前
准备升级到Android16,自适应布局应该如何适配
android·google·kotlin
神仙别闹1 小时前
基于 PHP + MySQL 图书库存管理系统
android·mysql·php
zhangphil1 小时前
Android内存回收:GC、kswapd 和 mm_vmscan_direct_reclaim概述
android
plainGeekDev1 小时前
ContentProvider → Room + Repository
android·java·kotlin
plainGeekDev1 小时前
SQLite 手动升级 → Room Migration
android·java·kotlin
MemoriKu1 小时前
Flutter 相册 APP 视频模态稳定化实战:从视频抽帧、Embedding 元数据到 Android 真机启动修复
android·开发语言·前端·flutter·架构·音视频·embedding