Android 5.0以上系统Toast不显示的解决方案

问题分析

开发中我们经常会在适配5.0以后的机型遇到各种各样的问题,其中有一个不大不小的问题就是:Toast不显示问题

其原因是:用户使用android 5.0以上的系统在安装APP时,将消息通知的权限关闭掉了。实际上用户本意只是想关闭Notification,但是Toast的show方法中有调用INotificationManager这个类,而这个类在用户关闭消息通知权限的同时被禁用了,所以我们的吐司无法显示。

Toast.show()

效果图

自定义Toast(上)与Toast(下)比对

问题解决

既然系统不允许我们调用Toast,那么我们就自立门户——自己写一个Toast出来。我们总体的思路是:在Activity的布局中添加View实现Toast的效果。

  • Toast背景shape定义 我们知道shape的背景是一个半透明黑色的圆角效果:

Toast 因此我们使用的是shape的corners和solid结点:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#99000000" />
    <corners android:radius="8dp" />
</shape>
  • 定义布局 布局中我们主要使用TextView控件,设置相应的边距和背景即可,布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mbContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="200dp"
    android:gravity="bottom|center"
    android:orientation="vertical"
    android:paddingLeft="50dp"
    android:paddingRight="50dp">

    <LinearLayout android:id="@+id/toast_linear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_toastutils_bg"
        android:gravity="bottom|center"
        android:orientation="vertical"
        android:padding="8dp">

        <TextView android:id="@+id/mbMessage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_margin="5dp"
            android:layout_weight="1"
            android:gravity="center"
            android:shadowColor="#BB000000"
            android:shadowRadius="2.75"
            android:textSize="12sp"
            android:textColor="#FFFFFFFF" />
    </LinearLayout>
</LinearLayout>
  • java代码逻辑 自定义Toast的java代码逻辑主要模仿系统Toast的makeText()、show()两个方法,此外还需要reset()方法,实现Toast显示过程中Activity切换时context也随之切换,关键代码如下: makeText(Context context, String message, int HIDE_DELAY)方法:
public static ToastUtils makeText(Context context, String message,
                                  int HIDE_DELAY) {
    if (mInstance == null) {
        mInstance = new ToastUtils(context);
    } else {
        // 考虑Activity切换时,Toast依然显示
        if (!mContext.getClass().getName().endsWith(context.getClass().getName())) {
            mInstance = new ToastUtils(context);
        }
    }
    if (HIDE_DELAY == LENGTH_LONG) {
        mInstance.HIDE_DELAY = 2500;
    } else {
        mInstance.HIDE_DELAY = 1500;
    }
    mTextView.setText(message);
    return mInstance;
}

makeText(Context context, int resId, int HIDE_DELAY)方法

public static ToastUtils makeText(Context context, int resId, int HIDE_DELAY) {
    String mes = "";
    try {
        mes = context.getResources().getString(resId);
    } catch (Resources.NotFoundException e) {
        e.printStackTrace();
    }
    return makeText(context, mes, HIDE_DELAY);
}

show()方法

public void show() {
    if (isShow) {
        // 若已经显示,则不再次显示
        return;
    }
    isShow = true;
    // 显示动画
    mFadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
    // 消失动画
    mFadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
    mFadeOutAnimation.setDuration(ANIMATION_DURATION);
    mFadeOutAnimation
            .setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    // 消失动画后更改状态为 未显示
                    isShow = false;
                }
                @Override
                public void onAnimationEnd(Animation animation) {
                    // 隐藏布局,不使用remove方法为防止多次创建多个布局
                    mContainer.setVisibility(View.GONE);
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });
    mContainer.setVisibility(View.VISIBLE);
    mFadeInAnimation.setDuration(ANIMATION_DURATION);
    mContainer.startAnimation(mFadeInAnimation);
    mHandler.postDelayed(mHideRunnable, HIDE_DELAY);
}
  • 方法调用 自定义Toast的使用与系统Toast类似,调用方法如下: ToastUtils.makeText(context, "消息内容",ToastUtils.LENGTH_SHORT).show();

代码链接

代码已上传Github,点击这里查看详细。

参考链接

当关闭通知消息权限后无法显示系统Toast的解决方案

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏增长技术

BaseRecyclerViewAdapterHelper

#如何使用它? 先在 build.gradle 的 repositories 添加:

78110
来自专栏封碎

让自己的Android应用支持appwidget 博客分类: Android AndroidOSAccessUP

经常看到一些教程教你如何写appwidget,但是,你知道你的appwidget是如何被添加到桌面上的吗? 一般的,如果是做桌面的童鞋,基本上都会让自己的...

16030
来自专栏Java后端生活

购物APP项目开发(1)——菜单开发

16240
来自专栏木头编程 - moTzxx

Google官方 下拉刷新组件SwipeRefreshLayout 简单实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

28430
来自专栏用户2442861的专栏

android 多条件筛选菜单效果

http://blog.csdn.net/u011733020/article/details/51002746

1.1K20
来自专栏木头编程 - moTzxx

跑马灯 TextView效果设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

20920
来自专栏james大数据架构

实例演示Android异步加载图片

本文给大家演示异步加载图片的分析过程。让大家了解异步加载图片的好处,以及如何更新UI。 首先给出main.xml布局文件: 简单来说就是 LinearLayou...

22250
来自专栏Android干货

Volley网络连接

30370
来自专栏Android干货

Android 购物车功能的实现

53350
来自专栏james大数据架构

实例演示Android异步加载图片

本文给大家演示异步加载图片的分析过程。让大家了解异步加载图片的好处,以及如何更新UI。 首先给出main.xml布局文件: 简单来说就是 LinearLayou...

30780

扫码关注云+社区

领取腾讯云代金券