我有一个应用程序显示自定义通知。问题是在Android 5中运行时,通知栏中的小图标显示为白色。我该如何解决这个问题?


当前回答

alpha-channel是Android用于通知图标的图像的唯一数据:

Alpha == 1:像素显示为白色 alpha == 0:像素显示为您选择的Notification.Builder#setColor(int)

https://developer.android.com/about/versions/android-5.0-changes.html上提到了这一点:

系统会忽略操作图标和主通知图标中的所有非alpha通道。您应该假设这些图标都是纯alpha的。

几乎所有的内置绘图似乎都适合alpha图像,所以你可能会使用类似的东西:

Notification.Builder.setColor(Color.RED)
                    .setSmallIcon(android.R.drawable.star_on)

但我仍在寻找官方证实这一点的API文档。

在Android 22上测试。

其他回答

您需要导入单色透明PNG图像。所以你可以设置小图标的图标颜色。否则,它将显示白色在一些设备,如MOTO

另一种选择是利用特定于版本的可绘制(mipmap)目录为Lollipop和以上版本提供不同的图形。

在我的应用程序中,“v21”目录包含带有透明文本的图标,而其他目录包含非透明版本(适用于比棒棒糖更老的Android版本)。

它应该是这样的:

这样,你就不需要检查代码中的版本号,例如:

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
        .setSmallIcon(R.mipmap.ic_notification)
        .setContentTitle(title)
        .setContentText(message)
        .setAutoCancel(true)
        .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

同样,如果您使用“icon”属性,则可以在GCM有效负载中引用“ic_notification”(或您选择的任何名称)。

https://developers.google.com/cloud-messaging/http-server-ref#notification-payload-support

这是Android用来显示通知图标的代码:

// android_frameworks_base/packages/SystemUI/src/com/android/systemui/
//   statusbar/BaseStatusBar.java

if (entry.targetSdk >= Build.VERSION_CODES.LOLLIPOP) {
    entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
} else {
    entry.icon.setColorFilter(null);
}

所以你需要将目标sdk版本设置为<21,图标将保持颜色。这是一个丑陋的解决方案,但它做到了预期的效果。无论如何,我真的建议遵循谷歌的设计准则:“通知图标必须完全是白色的。”

下面是你如何实现它:

如果你使用Gradle/Android Studio来构建应用,请使用build. Gradle:

defaultConfig {
    targetSdkVersion 20
}

否则(Eclipse等)使用AndroidManifest.xml:

<uses-sdk android:minSdkVersion="..." android:targetSdkVersion="20" />

公认的答案并不(完全)正确。当然,它使通知图标显示颜色,但这样做有一个很大的缺点-通过设置目标SDK低于Android棒棒糖!

如果你通过将目标SDK设置为20来解决白色图标的问题,你的应用将不会针对Android Lollipop,这意味着你不能使用Lollipop特有的功能。

看看http://developer.android.com/design/style/iconography.html,你会看到白色风格的通知是如何显示在Android棒棒糖。

在Lollipop中,谷歌还建议您使用将显示在(白色)通知图标后面的颜色- https://developer.android.com/about/versions/android-5.0-changes.html

因此,我认为更好的解决方案是在应用程序中添加一个轮廓图标,并在设备运行Android Lollipop时使用它。

例如:

Notification notification = new Notification.Builder(context)
            .setAutoCancel(true)
            .setContentTitle("My notification")
            .setContentText("Look, white in Lollipop, else color!")
            .setSmallIcon(getNotificationIcon())
            .build();

    return notification;

并且,在getNotificationIcon方法中:

private int getNotificationIcon() {
    boolean useWhiteIcon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP);
    return useWhiteIcon ? R.drawable.icon_silhouette : R.drawable.ic_launcher;
}

如果你正在使用GoogleFireBaseMessaging,你可以在“通知”有效载荷中设置“图标id”(它帮助我解决了白色栏图标的问题):

{
    "to":"<fb_id>",
    "priority" : "high",
    "notification" : 
    {
        "title" : "title",
        "body" : "body" ,
        "sound" : "default",
        "icon" : "ic_notification"
    }
}

将ic_notification设置为R.drawable中自己的id。