在Android 5棒棒糖中,通知栏图标变成白色

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

206106 次浏览

这是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" />

android:targetSdkVersion="20"应该是<21

公认的答案并不(完全)正确。当然,它使通知图标显示颜色,但这样做有一个很大的缺点-通过设置目标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;
}

完全同意用户Daniel Saidi的观点。为了有ColorNotificationIcon,我写这个答案。

为此,你必须创建像Silhouette这样的图标,并在你想添加Colors的地方创建一些Transparent部分。也就是说,

enter image description here

你可以使用

.setColor(your_color_resource_here)

注意: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的指令都在谷歌开发人员控制台通知指南行处给出。

首选通知图标大小24x24dp

mdpi    @ 24.00dp   = 24.00px
hdpi    @ 24.00dp   = 36.00px
xhdpi   @ 24.00dp   = 48.00px

更多信息请参考通知图标大小的链接。

我也遇到过同样的问题,那是因为我的应用通知图标不平坦。对于android版本,你的应用通知图标应该是扁平的,不要使用带有阴影的图标。

下面的代码在所有android版本上都运行得很好。

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());
}
< br > < p >错误的图标 enter image description here

正确的图标

enter image description here

从manifest.xml中删除android:targetSdkVersion="21"。它会起作用的! 从这一点上看,在你的apk中没有任何问题,这只是一个技巧,我应用这个,我在通知

中发现了彩色图标
为了避免通知图标变成白色,使用“剪影”图标。透明背景图片。 你可以使用Irfanview来构建它们:

  • 选择一个图片,打开IrfanView,按F12为绘图工具,如果需要,清洁图片(删除不需要的部分,平滑和抛光)
  • Image / Decrease Color Depth到2(对于一个黑色&白图)
  • Image / Negative(用于黑白图片)
  • Image / Resize/Resample到144 x 144(使用大小方法“调整大小”而不是“重新采样”,否则图片将再次增加到每像素24色位(24 BPP)
  • File / Save as PNG,选中Show option dialog,选中Save Transparent Color,单击Save,然后单击图像中的黑色设置透明颜色

Android似乎只使用drawable-xxhdpi图像分辨率(144 x 144),因此将生成的ic_notification.png文件复制到\AndroidStudio\Projects\...\app\src\main\res\drawable-xxhdpi。在代码中使用.setSmallIcon(R.drawable.ic_notification),或者像Daniel Saidi上面建议的那样使用getNotificationIcon()

你也可以使用Roman Nurik的Android Asset Studio

阿尔法通道是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上测试。

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

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

File system

它应该是这样的:

Android Studio

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

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已经改变了在通知栏中显示通知图标的指导方针。 官方文档说:“更新或删除涉及颜色的资产。系统会忽略操作图标和主通知图标中的所有非alpha通道。您应该假设这些图标都是纯alpha的。系统以白色绘制通知图标,深灰色绘制操作图标。” 用外行的术语来说,这意味着“将图像中所有不想显示的部分转换为透明像素。所有颜色和不透明像素都显示为白色"

你可以通过这里的截图看到如何做到这一点的详细信息 https://blog.clevertap.com/fixing-notification-icon-for-android-lollipop-and-above/ < / p >

希望这能有所帮助

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

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

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

根据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)

现在android studio提供了一个插件形象资产,它将在所有需要的drawbale文件夹中生成图标

形象资产 Studio帮助你创建不同密度的各种类型的图标,并告诉你它们将被放置在你的项目中的确切位置。它包括调整图标和添加背景的工具,同时在预览窗格中显示结果,因此它们完全按照您的预期显示。这些工具可以极大地简化图标设计和导入过程。

你可以通过点击新建>来访问形象资产,点击图像资产选项,它将显示如下窗口

enter image description here

enter image description here

通知是灰度,如下所述。不管别人写了什么,它们都不是黑白分明的。你可能见过带有多种色调的图标,比如网络强度条。

在API 21 (Lollipop 5.0)之前,彩色图标可以工作。您可以强制应用程序以API 20为目标,但这会限制应用程序可用的特性,因此不建议这样做。您可以测试正在运行的API级别,并适当地设置颜色图标或灰度图标,但这可能不值得。在大多数情况下,最好使用灰色图标。

图像有四个通道,RGBA(红/绿/蓝/ alpha)。对于通知图标,Android忽略R、G和B通道。唯一重要的通道是Alpha,也称为不透明度。用编辑器设计图标,让您可以控制绘图颜色的Alpha值。

Alpha值如何生成灰度图像:

  • Alpha = 0(透明)-这些像素是透明的,显示背景颜色。
  • Alpha = 255(不透明)-这些像素是白色的。
  • Alpha = 1…254 -这些像素正是你所期望的,提供透明和白色之间的阴影。

setColor改变它:

  • < p > NotificationCompat.Builder.setColor(int argb)打电话。来自Notification.color的文档:

    强调色(与颜色中的常量类似的ARGB整数)将在显示此通知时由标准样式模板应用。当前的模板设计通过将图标图像(白色模板)覆盖在该颜色的字段之上来构造一个彩色的标题图像。Alpha分量被忽略。

    我的测试setColor显示Alpha组件被忽略;相反,它们仍然提供灰度。较高的Alpha值使像素变白。较低的Alpha值将在通知区域中将一个像素转换为背景颜色(我的设备为黑色),或在下拉通知中转换为指定的颜色。(似乎其他人报告的行为略有不同,所以要注意!)

我也遇到了太多的问题,但在互联网上搜索后,我找到了这个问题的不同解决方案。让我总结一下所有的解决方案并解释一下:

注意:此解决方案适用于Phonegap cordova用户

  1. 使用实例

<preference name="android-targetSdkVersion" value="20"/>

你需要将android-targetSdkVersion的值设置为小于21。 所以在设置这个值后,通知图标图像将出现到Android 6(棉花糖),它不会在Android 7(牛轧糖)工作。

    修改配置文件中的statusbarStyle。 李例子 < / >

<preference name="StatusBarStyle" value="lightcontent" />

但是这个解决方案只有当你的应用程序被打开时才会工作。 所以,我猜这个解决方案不是最好的解决方案,但它适用于许多用户
  1. 使图标透明。 这个方法对很多人都有效。 实际上,在本地应用程序的开发中,我们需要为他们提供三个图像: (一)应用程序图标 (b)通知图标 (c)状态栏图标图像,但在混合移动应用程序开发的情况下,没有这样做的选项。 所以让你的图标透明,这个解决方案将解决你的问题

我相信上述解决方案之一将为您的问题工作。

供您参考:如果图标没有出现,请确保您的本地或远程通知配置包含正确的图标名称

'largeIcon' => 'ic_launcher',
'smallIcon' => 'ic_launcher' // defaults to ic_launcher,

在app gradle中混合这两个东西

 defaultConfig {
applicationId "com.example.abdulwahidvi.notificationproblem"
minSdkVersion 16
//This is the version that was added by project by default
targetSdkVersion 26 <------ default
// Changed it to version 20
targetSdkVersion 20 <------ mine


versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

我认为现在谈论API 21已经太晚了,但我找到了一个简单的方法。

使用“自定义通知(自定义布局)”时,

RemoteView的

setImageViewResource(int viewId, int srcId);

而且

setImageViewUri(int viewId, Uri uri);

使这些图像白色的棒棒糖(API 21)。

但是当使用

setImageViewBitmap(int viewId, Bitmap bitmap);

图像不会变成白色面具!

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

根据文档,通知图标必须是白色的,因为Android 3.0 (API Level 11):

https://developer.android.com/guide/practices/ui_guidelines/icon_design_status_bar

"状态栏图标是由透明的白色像素组成的 背景,使用alpha混合用于光滑的边缘和内部 适当的纹理。" < / p >