我有一个应用程序显示自定义通知。问题是在 Android 5 上运行时,通知栏中的小图标显示为白色。如何解决这个问题?
我有一个应用程序显示自定义通知。问题是在 Android 5 上运行时,通知栏中的小图标显示为白色。如何解决这个问题?
接受的答案并不完全正确。确实,它可以使通知图标显示为彩色,但是这样做存在一个很大的缺点——将目标SDK设置为低于Android Lollipop!
如果您按照建议将目标SDK设置为20来解决白色图标问题,则您的应用程序将无法针对Android Lollipop进行优化,这意味着您无法使用Lollipop特定的功能。
查看http://developer.android.com/design/style/iconography.html,您将看到白色风格是Android Lollipop中通知的预期显示方式。
在Lollipop中,Google还建议您使用一种颜色来显示(白色)通知图标的背景-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;
}
ctrl+f
并输入 notification
时,它找不到任何内容。 - user25我完全同意用户Daniel Saidi的观点。为了使通知图标有颜色,我写下了这个答案。
为此,您需要制作像剪影一样的图标,并在您想要添加颜色的地方将某些部分设置为透明。即,
您可以使用以下代码添加颜色:
.setColor(您的颜色资源在此处)
注意:setColor仅在Lollipop中可用,因此您需要检查OSVersion。
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Notification notification = new Notification.Builder(context)
...
} else {
// Lollipop specific setColor method goes here.
Notification notification = new Notification.Builder(context)
...
notification.setColor(your_color)
...
}
你也可以使用Lollipop
作为目标SDK
来实现这一点。NotificationIcon
的所有说明都在Google开发者控制台通知指南中。mdpi @ 24.00dp = 24.00px
hdpi @ 24.00dp = 36.00px
xhdpi @ 24.00dp = 48.00px
还可以参考通知图标大小了解更多信息。
setColor
,在这两种情况下它都忽略了颜色但是没有崩溃。那么我可以安全地省略检查操作系统版本吗? - Maria这是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
,这样图标就会保持彩色。这是一个丑陋的解决方法,但它确实实现了预期效果。无论如何,我强烈建议遵循Google的设计准则:"通知图标必须完全是白色的。"
以下是您可以实现它的方式:
如果您使用Gradle / Android Studio构建应用程序,请使用build.gradle
:
defaultConfig {
targetSdkVersion 20
}
否则(使用Eclipse等)请使用AndroidManifest.xml
:<uses-sdk android:minSdkVersion="..." android:targetSdkVersion="20" />
IrfanView
中打开,按F12键进入绘画工具,如果需要清理图片(去除不必要的部分,平滑和抛光)
- 图像/减少色深度
为2(对于黑白图片)
- 图像/负数
(对于黑底白字的图片)
- 图像/调整大小/重新采样
为144 x 144(使用大小方法"调整大小"而不是"重新采样",否则图片会再次增加到24位色深(24 BPP))
- 文件/另存为PNG
,勾选显示选项对话框
,勾选保存透明颜色
,单击保存
,然后单击图像中的黑色以设置透明颜色。ic_notification.png
文件复制到\AndroidStudio\Projects\...\app\src\main\res\drawable-xxhdpi
. 在您的代码中使用.setSmallIcon(R.drawable.ic_notification)
,或者像Daniel Saidi上面建议的那样使用getNotificationIcon()
。您也可以使用Roman Nurik的Android Asset Studio。另一种选择是利用特定于版本的可绘制(mipmap)目录,为Lollipop及以上版本提供不同的图形。
在我的应用中,“v21”目录包含带有透明文本的图标,而其他目录包含非透明版本(适用于早于Lollipop的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);
同样地,如果您在GCM有效负载中使用"icon"属性,则可以在其中引用"ic_notification"(或任何您选择的名称)。有关更多信息,请参见https://developers.google.com/cloud-messaging/http-server-ref#notification-payload-support。setColor
呢? - Daniel根据 Android 设计指南,您必须为builder.setSmallIcon(R.drawable.some_notification_icon);
使用剪影,但如果您仍想显示彩色图标作为通知图标,这里是针对棒棒糖及以上版本的技巧:使用以下代码。largeIcon 将充当主要通知图标,并且您还需要为 smallIcon 提供剪影,因为它会显示在 largeIcon 的右下角。
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
builder.setColor(context.getResources().getColor(R.color.red));
builder.setSmallIcon(R.drawable.some_notification_icon);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher));
}
在棒棒糖版本之前,只需在构建器中使用.setSmallIcon(R.mipmap.ic_launcher)
。
private void sendNotification(String msg) {
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, CheckOutActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg).setLights(Color.GREEN, 300, 300)
.setVibrate(new long[] { 100, 250 })
.setDefaults(Notification.DEFAULT_SOUND).setAutoCancel(true);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(new Random().nextInt(), mBuilder.build());
}
错误的图标
正确的图标
Alpha通道是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上进行了测试。
setColor
,在这两种情况下它都忽略了颜色但是没有崩溃。那么我可以安全地省略检查操作系统版本吗? - Maria从manifest.xml中移除android:targetSdkVersion="21"
。它会起作用!这样做完全不会影响您的apk,这只是一个技巧,我使用它并在通知中发现了彩色图标。