美文网首页android小功能的实现Android知识Android技术知识
Android 5.0以上系统Toast不显示的解决方案

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

作者: 代码咖啡 | 来源:发表于2016-11-10 12:09 被阅读3718次

    问题分析

    开发中我们经常会在适配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的解决方案

    相关文章

      网友评论

      • yfyyfbyffcx:这种方法ToastUtils类还持有一个context静态成员变量
      • 爱夏天Eva:键盘弹窗时,看不见吐司了,请问这个怎么解决啊?
      • b5727ec12c20:首先谢谢作者提供这个解决方法 但我在使用时遇到个问题 就是使用这个toast在A界面弹出消失后 进入B界面 (B界面继承BaseActivity (同时实现reset()方法)) 再返回A界面时点击toast是除了显示有消息的toast外(会消失) 同时还会弹出一个无内容的toast的框 一直显示在界面 (我的认为是博主的toast的xml 默认是VISIBLE状态 虽然在初始化构造器设置了Gone
        private ToastUtils(Context context) {
        mContext = context;
        container = (ViewGroup) ((Activity) context)
        .findViewById(android.R.id.content);
        mView = ((Activity) context).getLayoutInflater().inflate(
        R.layout.toast_layout, container);
        mContainer = (LinearLayout) mView.findViewById(R.id.mbContainer);
        mContainer.setVisibility(View.GONE);
        mTextView = (TextView) mView.findViewById(R.id.mbMessage);
        }
        但是在show()结束时mContainer设置为VISIBLE mContainer.setVisibility(View.VISIBLE);
        mFadeInAnimation.setDuration(ANIMATION_DURATION);
        mContainer.startAnimation(mFadeInAnimation);
        mHandler.postDelayed(mHideRunnable, HIDE_DELAY); 这样xlm又显示了 虽然你写了个cancel的方法 但是没有被使用 目前我的解决办法是xml默认不显示 构造器设置mContainer设置为显示就可以解决 不知道作者怎么认为
        代码咖啡: @牛1牛2 学习了😄
      • liangqibin:效果不错!谢谢分享!

      本文标题:Android 5.0以上系统Toast不显示的解决方案

      本文链接:https://www.haomeiwen.com/subject/pnxxpttx.html