20. 通知的样式进阶:装饰性背景、圆形图标、大图标与小图标、通知的暗黑模式适配

通知做到这一步,基本功能已经没问题了。但说实话,想让用户一眼就记住你的 App,光靠系统默认样式是不够的。今天我们来聊聊怎么把通知做得更好看、更有个性。

我个人习惯把通知样式分为两类:一类是「能用就行」,另一类是「看了就想点」。今天讲的内容,就是帮你从前者跳到后者。

20.1 装饰性背景:让通知不再单调

Android 从 5.0 开始支持自定义通知背景。说白了,就是你可以给通知加一层「皮肤」。

实现方式很简单,通过 NotificationCompat.BuildersetColor() 方法就能设置背景色。但要注意,这个颜色只会在小图标区域生效,不是整个通知栏都变色。

// 设置通知的装饰性背景色
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle("订单提醒")
        .setContentText("您的包裹已到达")
        .setColor(ContextCompat.getColor(context, R.color.notification_accent))
        .setColorized(true);  // 关键:让颜色覆盖到整个通知区域

重点来了setColorized(true) 是 Android 12 新增的 API。没有它,你设置的颜色只会影响小图标。加上它,整个通知的背景都会变色。

我在项目中遇到过一个问题:有些国产手机对 setColorized 支持不好。比如某米手机,设置了颜色后通知反而变丑了。我的建议是——先判断系统版本,再决定是否启用这个特性。

小技巧:颜色选浅色系,比如淡蓝、浅绿。深色背景在暗黑模式下容易翻车。

20.2 圆形图标:头像就该是圆的

通知里显示用户头像,这是很常见的需求。但系统默认的大图标是方形的,看着有点愣。你想想看,微信、QQ 的头像都是圆的,为什么?因为圆形更亲和。

Android 没有直接提供「圆形大图标」的 API,但我们可以曲线救国——用 Person 类和 MessagingStyle

// 创建圆形头像的 Person 对象
Person person = new Person.Builder()
        .setIcon(Icon.createWithBitmap(getCircularBitmap(avatarBitmap)))
        .setName("张三")
        .build();

// 使用 MessagingStyle 显示
NotificationCompat.MessagingStyle style = new NotificationCompat.MessagingStyle(person)
        .addMessage("你好,在吗?", System.currentTimeMillis(), person);

Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_notification)
        .setStyle(style)
        .build();

这里有个坑:getCircularBitmap() 需要你自己实现。说白了就是把方形 Bitmap 裁剪成圆形。我一般用 Canvas 加 Xfermode 来做,代码大概这样:

public static Bitmap getCircularBitmap(Bitmap source) {
    int size = Math.min(source.getWidth(), source.getHeight());
    Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    canvas.drawCircle(size / 2f, size / 2f, size / 2f, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(source, 0, 0, paint);
    return output;
}

注意:大图标不要超过 64dp。我曾经见过有人传了 200dp 的图,结果通知栏直接卡死。系统会缩放,但缩放大图很吃性能。

20.3 大图标与小图标:分工明确

很多新手搞不清大图标和小图标的作用。我简单解释一下:

  • 小图标:显示在状态栏,16x16dp 左右。必须纯白色,带透明通道。这是系统的硬性要求。
  • 大图标:显示在通知正文旁边,64x64dp 左右。可以是彩色,用来展示头像、商品图等。

为什么要区分?因为状态栏空间有限,彩色图标会显得杂乱。而通知正文区域空间大,适合展示更多信息。

// 正确设置大小图标
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_small)      // 白色矢量图
        .setLargeIcon(bitmap)                    // 彩色位图
        .setContentTitle("新消息")
        .setContentText("您有一条未读消息");

避坑指南:小图标不要用彩色图。我曾经见过一个 App,小图标用了红色,结果在状态栏里变成一团黑。因为系统默认把小图标当作「蒙版」来处理,彩色部分会被忽略。

20.4 暗黑模式适配:别让通知变成「亮瞎眼」

Android 10 开始系统级支持暗黑模式。如果你的通知没有适配,在暗黑模式下会非常刺眼。说白了,就是白底黑字变成了黑底白字,但你的图标和背景色没变,结果就是一团糟。

适配暗黑模式,核心就两点:

  1. 图标颜色:使用 @color/notification_icon_color 这种主题色,而不是写死的颜色。
  2. 背景色:不要用纯白或纯黑,用系统提供的 ?attr/colorSurface
// 在 values/colors.xml 中定义
<color name="notification_bg">#FFFFFF</color>

// 在 values-night/colors.xml 中定义(暗黑模式)
<color name="notification_bg">#1E1E1E</color>

// 代码中使用
int bgColor = ContextCompat.getColor(context, R.color.notification_bg);
builder.setColor(bgColor);

嗯,这里要注意:setColorized(true) 在暗黑模式下要慎用。因为一旦你设置了颜色,系统就不会自动帮你做暗黑适配了。我一般只在亮色模式下用 setColorized,暗黑模式下就让它走默认样式。

我的习惯:在 onConfigurationChanged 里监听暗黑模式切换,然后重新构建通知。这样用户切换主题时,通知能立刻更新。

20.5 知识体系总览

说了这么多,我画了一张图帮你理清思路。通知样式进阶的核心就这四块:

通知样式进阶知识体系 通知样式进阶 装饰性背景 setColor() + setColorized() 圆形图标 Person + MessagingStyle 大图标与小图标 setSmallIcon + setLargeIcon 暗黑模式适配 values-night + 主题色 核心原则:美观 + 兼容 + 性能

这张图把今天的内容串起来了。你看,四个方向各司其职:背景色负责氛围,圆形图标负责亲和力,大小图标分工明确,暗黑模式保证体验一致性。

最后说一句:通知样式不是越花哨越好。我见过有人把通知做成了「圣诞树」,结果用户直接关掉了通知权限。适可而止,恰到好处,才是高手。


公众号:蓝海资料掘金营,微信deep3321