通知栏图标在Android 5 Lollipop中变成白色


207

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


拉胡尔·夏尔马和basiam这里有一个更好的答案- stackoverflow.com/questions/30795431/...
Rivu Chakraborty的

而不是5中的Android 6运行时,它发生在我身上
海梅·蒙托亚

当然,这恰好与Android 5+,当然也是在Android的6和7对这个问题的Android 5的时间为最新版本,并导致这一问题的功能在Android的5引入
亚历杭德罗·卡萨诺瓦

我认为说API等级21(Android 5.0),API等级22(Android 5.1),API等级23(Android 6.0)等更为准确。术语“ Android 5”含糊不清,因为您可能会谈论Android 5.0或Android 5.1,并且在测试通知和图标在API Level 22 Vs中的显示方式时。API Level 23,我意识到它们的行为有所不同。
Jaime Montoya'4

Answers:


269

接受的答案不正确(完全)。当然,它使通知图标显示为彩色,但是这样做有一个很大的缺点-通过将目标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;
}

34
您如何生成轮廓?我是没有Photoshop技能的开发人员,使用在线工具使背景透明仍然会产生白色图标。
Chaitanya

6
@Chaitanya使用GIMP :)
ByteHamster

4
此解决方案无法回答为何android构建过程会修改完全正确的PNG并对其进行压缩并删除Alpha通道的问题。
philk

6
developer.android.com/design/style/iconography.html导致material.google.com/style/icons.html,当我在该页面上按下ctrl+f并键入notification内容时,它什么也找不到...
user25

4
而不是从代码applay平台版本修饰符检查到drawable文件夹
-drawable

72

与用户Daniel Saidi完全同意。为了有ColorNotificationIcon我写这个答案。

为此,您必须将icon设为,SilhouetteTransparent在要添加的位置添加一些区域Colors。即

在此处输入图片说明

您可以使用添加颜色

.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参见Google Developer Console通知指南

首选通知图标大小为24x24dp

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

另请参阅此链接以获取通知图标大小,以获取更多信息。


4
这是将背景色设置为notification.setColor(your_color_resource_here)的
TejaDroid 2015年

1
因此,我尝试了此操作,当我下拉通知阴影时,通知图标的背景为彩色。但是,在托盘本身中,它仍然是白色图标
Stealth Rabbi

1
此解决方案是正确的。具有一个带有透明背面的通知图标。按轮廓,该图标不必仅是黑色的。图标可以具有颜色;它只是android L会将显示颜色转换为白色..而以前的android版本将按原样显示图标
Lakshay

我在下面的棒棒糖中添加setColor,显示ic_launcher图标很好,但在6.0中显示白色正方形图标,请帮助我
Harsha

我已经setColor在Kitkat(API 19)和IceCreamSandwich(API 15)上进行了测试,在两种情况下,它都忽略了颜色,但没有崩溃。那么我可以安全地省略检查操作系统版本吗?
玛丽亚

47

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

有什么解决方法吗?或者我该怎么做才能正确显示该图标或任何其他图标?
亚历杭德罗·卡萨诺瓦

阅读了Android源代码后,我找到了解决方法,因此我已经编辑了答案。
ByteHamster,2015年

4
非常感谢您的帮助,但是请您为我提供一些“背景信息”。我需要在哪里做?什么是“入口”?
亚历杭德罗·卡萨诺瓦

该代码取自AOSP,只是为了说明如何找到解决方法:)我添加了有关如何实现它的简短说明。
ByteHamster,2015年

这实际上有效。有人猜测为什么Google这样做吗?这是错误还是功能?
m02ph3u5 2015年

24

为避免通知图标变白,请为它们使用“剪影”图标,即。透明背景上的白色图像。您可以使用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)在你的代码,或使用getNotificationIcon()如丹尼尔·赛义迪以上建议。

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


我尝试使用photoshop转换图标,但失败了,但是作为irfanview迷,当我看到它时,我迅速尝试了一下,效果非常好。谢谢!
布鲁斯

15

另一个选择是利用特定于版本的drawable(mipmap)目录为Lollipop及更高版本提供不同的图形。

在我的应用中,“ v21”目录包含带有透明文本的图标,而其他目录包含非透明版本(适用于Lollipop之前的Android版本)。

文件系统

应该看起来像这样:

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


3
这可以正常工作,并且看起来像大多数Android解决方案。
谢尔盖·加林

您是在说如果android如果从版本中选择棒棒糖,则将从文件夹mipmap-21中选择图标;如果少于棒棒糖,它将从drawable中选择图标?
Lakshay

@Ian,目录方法适合每个android版本的资源,但是如何setColor以这种方式设置(不涉及额外的代码)?
丹尼尔(Daniel)

@Daniel颜色也可以在特定于版本的目录中,例如“ values”和“ values-v21”。
伊恩

12

根据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)与您的制造商一起使用。


11

现在android studio提供了一个插件 Image Asset,它将在所有必需的drawbale文件夹中生成图标

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

您可以通过单击新建>单击图像资产选项来访问 图像资产,它将显示在这样的窗口中:-

在此处输入图片说明

在此处输入图片说明


8

我遇到了同样的问题,这是因为我的应用程序通知图标不平坦。对于Android版本的Lollipop或什至低于Lollipop的应用,您的应用程序通知图标应该是扁平的,请勿将图标与阴影等配合使用。

以下是在所有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());
}

错误的图示
在此处输入图片说明

右边的图标

在此处输入图片说明


1
您到底在哪里解决问题?
IgorGanapolsky '16

如何创建正确的图标。有可能在线生成吗?任何工具?
Jiks '16

@Jiks是的,这里是链接
Muhammad Sohaib Ayub

7

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在Kitkat(API 19)和IceCreamSandwich(API 15)上进行了测试,在两种情况下,它都忽略了颜色,但没有崩溃。那么我可以安全地省略检查操作系统版本吗?
玛丽亚

@JohnLee我不认为它会崩溃,如果您不考虑它,它只会看起来很糟糕:-)
Ciro Santilli郝海东冠状病六四事件法轮功

3

android:targetSdkVersion="21"从manifest.xml中删除。它会工作!从这个apk中根本没有问题,这只是我应用的一个技巧,我在通知中发现了彩色图标


9
用系统玩“技巧”完全不好!没办法!
sud007 '16

3

通知是灰度的,如下所述。尽管其他人已经写过,但它们不是黑白的。您可能已经看到带有多种阴影的图标,例如网络强度条。

在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

  • 致电NotificationCompat.Builder.setColor(int argb)。从以下文档中Notification.color

    呈现此通知时,标准样式模板要应用的重音颜色(ARGB整数,如Color中的常量)。当前的模板设计通过将图标图像(以白色模版)覆盖在此颜色的字段上方来构造彩色标题图像。Alpha组件将被忽略。

    我对setColor的测试表明,忽略Alpha组件;相反,它们仍然提供灰度。较高的Alpha值会使像素变白。较低的Alpha值会将像素变为通知区域中的背景颜色(在我的设备上为黑色),或在下拉通知中变为指定的颜色。(似乎其他人报告的行为略有不同,因此请注意!)


2

android后的Lollipop版本android更改了在通知栏中显示通知图标的准则。官方文档说:“更新或删除涉及颜色的资产。系统会忽略操作图标和主通知图标中的所有非Alpha通道。您应假定这些图标仅是Alpha。系统以白色绘制通知图标和动作图标为深灰色。” 现在,用通俗易懂的术语来说,这意味着“将您不想显示的图像的所有部分转换为透明像素。所有颜色和非透明像素均以白色显示”

您可以在此处查看如何使用屏幕快照详细执行此操作 :https://blog.clevertap.com/fixing-notification-icon-for-android-lollipop-and-above/

希望有帮助


2

您需要导入单色透明PNG图像。因此,您可以设置小图标的图标颜色。否则在某些设备(例如MOTO)中它将显示为白色


1

如果您使用的是GoogleFireBaseMessaging,则可以在“通知”有效负载中设置“图标ID”(这有助于我解决白条图标问题):

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

R.drawable中的ic_notification设置为您自己的ID。


您在哪里放置了该图标?我得到的只是我应用程序的图标,我发现所有R.drawable文件都是二进制类文件。
shinzou'8

@kuhaku他指的是“可绘制”文件夹中的ic_launcher.png文件。
约翰逊

0

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

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

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

您需要将android-targetSdkVersion值设置为小于21。因此,在设置此值后,通知图标图像将显示到Android 6(棉花糖),直到在Android 7(牛轧糖)中都无法使用。这个解决方案对我有用。

  1. 更改配置文件中的statusbarStyle。

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

但是,仅当您的应用程序打开时,此解决方案才有效。因此,我想这个解决方案不是最好的解决方案,但是它对许多用户有效。

  1. 使您的图标透明。该解决方案适用于许多人。实际上,在开发本机应用程序时,我们需要为其提供三个图像:(a)应用程序图标(b)通知图标(c)状态栏图标图像,但是在混合移动应用程序开发的情况下,这样做。因此,使您的图标透明,此解决方案将解决您的问题。

而且我相信上述解决方案之一将可以解决您的问题。


0

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

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

0

我认为谈论API 21为时已晚,但是我找到了一种简单的方法。

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

RemoteView的

setImageViewResource(int viewId, int srcId);

setImageViewUri(int viewId, Uri uri); 

使这些图像在棒棒糖(API 21)上呈白色。

但是当使用

setImageViewBitmap(int viewId, Bitmap bitmap);

图像不会变白!



-3

在应用程序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"
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.