为了账号安全,请及时绑定邮箱和手机立即绑定

Android自定义通知样式适配

标签:
Android

温故而知新

Android通知有两种,默认通知与自定义通知。默认通知简单调用系统接口就能实现,如下:

5b8bd84100015b6510970422.jpg

发送默认通知

5b8bd8420001997e05500215.jpg

默认通知效果

自定义通知就稍微麻烦一些,需要定义一个layout文件,使用RemoteViews加载它并设置一些点击事件,

再设置到builder,如下:

5b8bd8420001266211620325.jpg

自定义通知代码

5b8bd8420001a68805500215.jpg

自定义通知效果

这个通知很简单,就是两行文本加上一个按钮,按钮具有单独的点击事件,点击后跳转到AnotherActivity。

注意:smallIcon对于自定义通知和默认通知都是必须的,否则通知显示不出来。道理很简单,

smallIcon需要在状态栏上显示,不设置怎么行。在5.0及以上,smallIcon必须符合

Material Design风格,即白色内容,透明背景。不然系统会使用默认的图片替换。

具体可参考Android通知栏微技巧,那些你所没关注过的小细节 标签: android通知通知栏微技巧

后面我会有一篇更详细的文章来介绍这个。contentIntent对于2.3及以下的系统是必须的,否则

发送通知时会抛异常。道理也很简单,Android 2.3及以下系统不支持给自定义通知上的元素绑定

单独的点击事件,因此必须设置整个通知的点击事件。

为什么要进行样式适配?

默认通知不存在样式适配的问题,因为默认通知的布局、颜色、背景什么的都是系统的,系统总会正确的

显示默认通知。但自定义通知就不一样了,自定义通知的布局完全由我们自己掌控,我们可以为元素设置

任何背景、颜色。那么,问题来了。Android通知栏的背景各种各样,不同的ROM有不同的背景,白色、

黑色、透明等。不同的Android版本通知栏背景也不一样,一旦我们为自定义通知上的元素设置了特定背景

或颜色,就肯定会带来兼容性问题(主要是文本啦)。这样的应用一大把,贴个图大家就明白了:

5b8bd842000134fa04800854.jpg

未适配的自定义通知

怎么适配?

适配的方式大概有两种,一种简单粗暴:为自定义通知设置固定的背景(上图中的360卫士就这么干的),

比如黑色。那么内容自然就是白色或近似白色。这样,在所有的手机上都能正常显示,不会出现在黑色

背景通知栏上显示良好,到了白色背景通知栏上就几乎啥也看不见。使用这种方案的应用太多了。我个人

很不推崇这种方式,这样会使得自定义通知在将近一半的手机上显示得很突兀,和系统的通知栏不够沉浸,

影响整体美观。另一种方案就稍微合理一些:通过读取系统的通知栏样式文件,获取到title和content

的颜色,进而将这个颜色设置到自定义通知上。现在切入主题,谈谈如何来更好的适配自定义通知。有过

锁屏开发经验的人应该知道,如果你的应用有读取系统通知栏的权限,那么每当应用程序发出一个通知,

你的应用都会收到对应的notification对象,这个时候,我们一般会执行以下操作:

5b8bd8430001c37210640232.jpg

获取并展示app通知

调用addView之后,应用程序的通知就会显示在我们的应用里。显然,上面的代码并没有对apply返回的

notificationItemLayout做任何其他操作,但确实这个View显示出来时就是样式良好的,可见,

notificationItemLayout本身就是带有样式的,即便是默认通知。那么方案来了!我们先构造一个默认通知:

5b8bd843000197c011130218.jpg

获取通知栏title的颜色

通知并不发送出去,只是用来获取通知栏title的颜色,如果你还想获取content的颜色,抱歉,

不能通过查找android.R.id.text来获取,这个字段是访问不到的。可通过反射获取,更好的办法

是先预先设置一个content,然后遍历viewGoup根据content内容找到对应的TextView再获取颜色。

拿到颜色后,可根据算法判断这个颜色是近似白色还是近似黑色,我们使用黑色作为基准色,使用方差

来计算这个颜色是否近似黑色:

5b8bd843000141a510650310.jpg

比较两个颜色是否近似

baseColor传入Color.BLACK,color传入刚刚获取到的title的颜色,根据我实测,阈值为180.0较为

合理。上述方法返回true,即表示title的颜色近似黑色,也就是说通知栏背景近似白色。

额,经验丰富的同学应该已经洞察到第二段代码存在的兼容性问题了:根据android.R.id.title去找

到title对应的TextView是不靠谱的,因为有些ROM厂商会把id改掉,导致找到的title为空。

同时还有另外一个问题:使用上述方法,Activity不能继承自AppCompatActivity(实测5.0以下机型

可以,5.0及以上机型不行),大致的原因是默认通知布局文件中的ImageView(largeIcon和smallIcon)

被替换成了AppCompatImageView,而在5.0及以上系统中,

AppCompatImageView的setBackgroundResource(int)未被标记为RemotableViewMethod,导致apply时抛异常。

为了解决这两个问题,我们改进getNotificationColor方法:

5b8bd8430001a7f209360243.jpg

改进后的方法

在getNotificationColorInternal中,设置一个默认的title文本,如果根据id找不到title,

则遍历notificationRoot根据设置的title文本找到title:

5b8bd8440001bf6a12400925.jpg

兼容厂商改id

在getNotificationColorCompat中,我们先构造一个默认通知,获取到默认通知的布局文件id,

并将布局加载到notificationRoot,此时,如果根据id找不到title,显然设置默认title的办法

已经失效了。如何从notificationRoot中找到title是个问题。我的解决办法是:反正都已经拿到

notificationRoot了,不如就遍历它,先找到其中的所有TextView,取字体最大的TextView作为title

(这是合理的,因为默认通知中最多也就4个TextView,分别是title、content、info、when,

title肯定是字体最大,最显眼的),并返回其颜色:

5b8bd8510001438711050841.jpg

兼容AppCompatActivity

实际测试

拿到了通知栏背景的颜色后,我们就可以加载不同样式的布局,达到适配的目的。代码如下:

5b8bd8520001543812210913.jpg

适配代码

效果:

5b8bd8530001de3405500226.jpg

Android 4.4黑色背景的通知栏


5b8bd85300011e3207190310.jpg

坚果手机白色版白色通知栏

原文链接:http://www.apkbus.com/blog-822415-75981.html

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消