消息栏通知Notification的那些事儿

前言

最近在开发过程中,用到了Notification的功能,需要实现一个自定义的布局。实现方式相信大家也都知道,就是通过RemoteViews来实现。但是在开发过程中还是遇到不少问题。

首先,还是有必要说明一下,RemoteViews主要被用于AppWidget和Notification,它描述一个在其它进程中显示的View。

RemoteViews 使用过程中遇到的问题

首先是关于 RemoteViews 设置的问题

Notification notification = new NotificationCompat.Builder(this)
                .setContent(remoteViews)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setTicker("您有新短消息,请注意查收!").build();

NotificationCompat.Builder是有提供setContent的方法来设置RemoteViews的。然而存在一个问题,通过setContent()方法获得的Notification是固定高度的。如果View的高度比默认高度要大的话,就会有一部分显示不出来。

那么如何设置能够不存在高度限定呢? 实际上也简单。

if(android.os.Build.VERSION.SDK_INT >= 16) {
            notification.bigContentView = remoteViews;
        }
 notification.contentView = remoteViews;

android 在sdk16的时候引入了通知的展开和收起的功能,通过两个手指滑动操作,这里 bigContentView 表示展开时的显示的View,而contentView 表示收起时显示的View。我们可以通过设置 bigContentView 来完全显示,但仍然需要注意几个点:

  • bigContentView是在sdk16的时候才引入的,所以一定不要忘记判断一下。对于小于16,的则只能定高了。

  • 就算是bigContentView 也是有最大高度的,其最大高度是256dp,而contentView 默认情况下高度为64p。

  • Notification 使用过程中, .setSmallIcon、setTicker 是一定要设置的。

自定义View 对背景色的适配

Android通知栏的背景各式各样,不同的ROM都适配有不同的背景。不同的Android版本通知栏背景也不一样,一旦我们为自定义通知上的元素设置了特定背景或颜色,就肯定会带来兼容性问题。

由此可以想到一种方法,将背景设为透明的,然后如果可以找到系统通知栏默认的文字样式,这样就可以显示出同样的效果了。

屏幕快照 2016-11-13 13.01.56.png

android 也确实提供了这样的样式,使用方式也简单,如下面这样设置即可。

android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"

同时还提供了其他样式,如 TextAppearance.StatusBar.EventContent.Time,TextAppearance.StatusBar.EventContent.Info 等都可以试试。

然而这并没有结束,5.0以后的版本,android 又修改了新的默认的样式,所以就需要我们新建layout-v21,添加新的适配文件。

屏幕快照 2016-11-13 13.27.23.png

设置的方式并没有什么不同

android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"

ok ,大功告成,来看一下效果。

白色背景:


截屏_20161113_133535.png

黑色背景:

Screenshot_20161113-134026.png

下面介绍一种大神的方案-大体的方式是: 通过获取系统通知栏Notification默认的标题颜色,然后比对色值,判断出通知栏背景的颜色是黑色域还是白色域,之后就可以选取相应的自定义通知栏。

对这个方案也测试了一下,vivo测试机 通知栏背景色是白色的,然而获得的标题的颜色也是白色的,也就是说 还是会出现 不可预知的问题。总之,学习一下还是可以的。

//逻辑相应代码
public class NoficationBar {

    private static final double COLOR_THRESHOLD = 180.0;

    private String DUMMY_TITLE = "DUMMY_TITLE";
    private int titleColor;

    public NoficationBar() {
    }

    //判断是否Notification背景是否为黑色
    public boolean isDarkNotificationBar(Context context) {
        return !isColorSimilar(Color.BLACK, getNotificationTitleColor(context));
    }



    //获取Notification 标题的颜色
    private int getNotificationTitleColor(Context context) {
        int color = 0;
        if (context instanceof AppCompatActivity) {
             color = getNotificationColorCompat(context);
        } else {
            color = getNotificationColorInternal(context);
        }
        return color;
    }

    //判断颜色是否相似
    public boolean isColorSimilar(int baseColor, int color) {
        int simpleBaseColor = baseColor | 0xff000000;
        int simpleColor = color | 0xff000000;
        int baseRed = Color.red(simpleBaseColor) - Color.red(simpleColor);
        int baseGreen = Color.green(simpleBaseColor) - Color.green(simpleColor);
        int baseBlue = Color.blue(simpleBaseColor) - Color.blue(simpleColor);

        double value = Math.sqrt(baseRed * baseRed + baseGreen * baseGreen + baseBlue * baseBlue);
        return value < COLOR_THRESHOLD;

    }

    //获取标题颜色
    private int getNotificationColorInternal(Context context) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setContentTitle(DUMMY_TITLE);
        Notification notification = builder.build();

        ViewGroup notificationRoot = (ViewGroup) notification.contentView.apply(context, new FrameLayout(context));
        TextView title = (TextView) notificationRoot.findViewById(android.R.id.title);
        if (title == null) { //如果ROM厂商更改了默认的id
            iteratorView(notificationRoot, new Filter() {
                @Override
                public void filter(View view) {
                    if (view instanceof TextView) {
                        TextView textView = (TextView) view;
                        if (DUMMY_TITLE.equals(textView.getText().toString())) {

                            titleColor = textView.getCurrentTextColor();
                        }
                    }
                }
            });
            return titleColor;
        } else {

            return title.getCurrentTextColor();
        }
    }


    private int getNotificationColorCompat(Context context) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        Notification notification = builder.build();
        int layoutId = notification.contentView.getLayoutId();
        ViewGroup notificationRoot = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null);
        TextView title = (TextView) notificationRoot.findViewById(android.R.id.title);
        if (title == null) {
            final List<TextView> textViews = new ArrayList<>();
            iteratorView(notificationRoot, new Filter() {
                @Override
                public void filter(View view) {
                    if (view instanceof TextView) {
                        textViews.add((TextView) view);
                    }
                }
            });
            float minTextSize = Integer.MIN_VALUE;
            int index = 0;
            for (int i = 0, j = textViews.size(); i < j; i++) {
                float currentSize = textViews.get(i).getTextSize();
                if (currentSize > minTextSize) {
                    minTextSize = currentSize;
                    index = i;
                }
            }
            textViews.get(index).setText(DUMMY_TITLE);
            return textViews.get(index).getCurrentTextColor();
        } else {
            return title.getCurrentTextColor();
        }

    }


    private void iteratorView(View view, Filter filter) {
        if (view == null || filter == null) {
            return;
        }
        filter.filter(view);
        if (view instanceof ViewGroup) {
            ViewGroup container = (ViewGroup) view;
            for (int i = 0, j = container.getChildCount(); i < j; i++) {
                View child = container.getChildAt(i);
                iteratorView(child, filter);
            }
        }

    }

    interface Filter {
        void filter(View view);
    }

}

参考文章: http://www.jianshu.com/p/426d85f34561

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容