【问题标题】:Notification bar icon turns white in Android 5 LollipopAndroid 5 Lollipop 中的通知栏图标变为白色
【发布时间】:2015-04-07 21:12:58
【问题描述】:

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

【问题讨论】:

  • Rahul Sharma 和 basiam 在这里有更好的答案 - stackoverflow.com/questions/30795431/…
  • 在 Android 6 而非 5 中运行时会发生这种情况。
  • 当然,它发生在 Android 5+ 上,当然也发生在 Android 6 和 7 中。到问题发生时,Android 5 是最新版本,导致此问题的功能是在 Android 5 中引入的。
  • 我觉得说API Level 21(Android 5.0)、API Level 22(Android 5.1)、API Level 23(Android 6.0)等比较准确。“Android 5”这个词比较含糊因为你可能在谈论 Android 5.0 或 Android 5.1,当我测试通知和图标在 API Level 22 中出现的方式时。 API 级别 23,我意识到它们的行为不同。

标签: android android-notifications android-5.0-lollipop


【解决方案1】:

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

【讨论】:

  • 如何生成剪影?我是没有 Photoshop 技能的开发人员,使用在线工具使背景透明仍然会导致白色图标。
  • @Chaitanya 使用 GIMP :)
  • 这个解决方案没有回答为什么 android 构建过程会修改一个完全正确的 PNG 并对其进行压缩并删除 alpha 通道的问题。
  • developer.android.com/design/style/iconography.html 导致material.google.com/style/icons.html,当我按ctrl+f 并在该页面上输入notification 时,它找不到任何东西......
  • 而不是从代码应用平台版本修改器检查到可绘制文件夹 - drawable / drawable-v21 并放置正确的图标
【解决方案2】:

完全同意用户 Daniel Saidi 的观点。为了让Color 成为NotificationIcon,我正在写这个答案。

为此,您必须制作Silhouette 之类的图标,并在您想添加Colors 的任何地方制作一些部分Transparent。即,

您可以使用

添加颜色

.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 Notification Guide Lines 给出。

首选通知图标大小 24x24dp

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

有关更多信息,请参阅此链接以获取 Notification Icon Sizes

【讨论】:

  • 将背景颜色设置为 notification.setColor(your_color_resource_here)
  • 所以我试过这个,当我拉下通知阴影时,通知图标有彩色背景。但是,在托盘本身中,它仍然是一个白色图标
  • 这个解决方案是对的..有一个透明的通知图标..通过剪影,图标不必只有黑色..图标可以有颜色;只是 android L 会将显示颜色转换为白色..而以前的 android 版本将按原样显示图标
  • 我正在为下面的棒棒糖添加 setColor,显示 ic_launcher 图标很好,但在 6.0 中显示白色方形图标请帮助我
  • 我已经在 Kitkat (API 19) 和 IceCreamSandwich (API 15) 上测试了 setColor,在这两种情况下它都忽略了颜色但没有崩溃。那么我可以安全地省略检查操作系统版本吗?
【解决方案3】:

这是 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 版本设置为 &lt;21,图标将保持彩色。这是一个丑陋的解决方法,但它完成了预期的工作。 无论如何,我真的建议关注 Google 的 Design Guidelines “通知图标必须全白。”

您可以通过以下方式实现它:

如果您使用 Gradle/Android Studio 构建应用,请使用 build.gradle

defaultConfig {
    targetSdkVersion 20
}

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

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

【讨论】:

  • 有什么解决方法吗?或者我该怎么做才能正确显示该图标或任何其他图标?
  • 我已经编辑了我的答案,因为我在阅读 Android 源代码后找到了解决方法。
  • 非常感谢您的帮助,但请您为我提供一些“上下文”。我需要在哪里这样做?什么是“入口”?
  • 代码取自 AOSP 只是为了展示我是如何找到解决方法的 :) 我添加了一个关于如何实现它的小说明。
  • 这确实有效。任何猜测为什么谷歌这样做?这是错误还是功能?
【解决方案4】:

为避免通知图标变白,请为它们使用“剪影”图标,即。白色透明背景图像。 您可以使用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's Android Asset Studio

【讨论】:

  • 我尝试使用 Photoshop 转换我的图标但失败了,但是作为一个 irfanview 的粉丝,当我看到它时我很快就尝试了它并且效果非常好。谢谢!
【解决方案5】:

另一种选择是利用特定于版本的可绘制 (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);

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

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

【讨论】:

  • 这很有效,看起来像是最适合 Android 的解决方案。
  • 你是说如果版本是棒棒糖,android会从文件夹mipmap-21中选择图标,如果小于棒棒糖,它会从drawable中选择?
  • @Ian ,目录方法适用于每个 android 版本的资源,但是如何设置 setColor(不涉及额外代码)?
  • @Daniel 颜色也可以在特定于版本的目录中,例如“价值观”和“价值观-v21”。
【解决方案6】:

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

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

您可以通过单击新建>单击图像资源选项访问图像资源,它将显示如下所示的窗口:-

【讨论】:

    【解决方案7】:

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

    在棒棒糖之前,您的 builder 只能使用 .setSmallIcon(R.mipmap.ic_launcher)

    【讨论】:

      【解决方案8】:

      我遇到了同样的问题,这是因为我的应用通知图标不平坦。对于 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());
      }
      

      图标错误

      右图标

      【讨论】:

      • 你到底是在哪里解决问题的?
      • 如何创建正确的图标。可以在线生成吗?有什么工具吗??
      • @Jiks 是的,这里是link
      【解决方案9】:

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

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

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

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

      几乎所有built-in drawables 似乎都适合于此,因此您可以使用类似的东西:

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

      但我仍在寻找官方确认的API doc

      在 Android 22 上测试。

      【讨论】:

      • 我在 Kitkat (API 19) 和 IceCreamSandwich (API 15) 上测试了 setColor,在这两种情况下它都忽略了颜色,但没有崩溃。那么我可以安全地省略检查操作系统版本吗?
      • @JohnLee 我不认为它会崩溃,如果你不考虑它可能看起来很糟糕:-)
      【解决方案10】:

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

      【讨论】:

      • 用系统玩“把戏”的想法太糟糕了!不是解决方案!
      【解决方案11】:

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

      在 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 值将像素转换为通知区域中的背景颜色(我的设备上为黑色),或下拉通知中的指定颜色。 (似乎其他人报告的行为略有不同,所以请注意!)

      【讨论】:

        【解决方案12】:

        发布 android Lollipop 版本 android 更改了在通知栏中显示通知图标的准则。 官方文档说“更新或删除涉及颜色的资产。系统会忽略操作图标和主通知图标中的所有非 alpha 通道。您应该假设这些图标将是 alpha-only。系统将通知图标绘制为白色和深灰色的动作图标。” 现在这在外行术语中的意思是“将您不想显示的图像的所有部分转换为透明像素。所有颜色和非透明像素都显示为白色”

        您可以在此处通过屏幕截图详细了解如何执行此操作 https://blog.clevertap.com/fixing-notification-icon-for-android-lollipop-and-above/

        希望有帮助

        【讨论】:

          【解决方案13】:

          您需要导入单色透明PNG图片。所以你可以设置小图标的图标颜色。否则在 MOTO 等设备上会显示为白色

          【讨论】:

            【解决方案14】:

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

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

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

            【讨论】:

            • 你把那个图标放在哪里了?我得到的只是我的应用程序的图标,我找到的所有 R.drawable 文件都是二进制类文件。
            • @kuhaku 他指的是“drawable”文件夹中的 ic_launcher.png 文件。
            【解决方案15】:

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

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

            1. Example

            &lt;preference name="android-targetSdkVersion" value="20"/&gt;

            您需要将您的 android-targetSdkVersion 值设置为小于 21。 所以设置此值后,通知图标图像会一直显示到 Android 6(Marshmallow),它不会在 Android 7(Nougat) 中工作。 这个解决方案对我有用。

            1. 更改配置文件中的状态栏样式。 Example

            &lt;preference name="StatusBarStyle" value="lightcontent" /&gt;

            但此解决方案仅在您的应用打开时才有效。 所以,我想这个解决方案不是最好的解决方案,但它适用于许多用户。

            1. 使您的图标透明。 该解决方案适用于许多人。 实际上,在 Native 应用程序的开发中,我们需要为它们提供三个图像: (a)应用程序图标 (b)通知图标 (c)状态栏图标图像,但在混合移动应用程序开发的情况下,没有这样做的选项。 所以让你的图标透明,这个解决方案将解决你的问题。

            而且我确信上述解决方案之一将适用于您的问题。

            【讨论】:

              【解决方案16】:

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

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

              【讨论】:

                【解决方案17】:

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

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

                RemoteView 的

                setImageViewResource(int viewId, int srcId);
                

                setImageViewUri(int viewId, Uri uri); 
                

                在 Lollipop (API 21) 上使这些图像变为白色。

                但使用时

                setImageViewBitmap(int viewId, Bitmap bitmap);
                

                图像不会变成白色蒙版!

                【讨论】:

                  【解决方案18】:

                  根据文档,自 Android 3.0(API 级别 11) 起,通知图标必须为白色:

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

                  “状态栏图标仅由透明上的白色像素组成 背景,alpha 混合用于平滑边缘和内部 适当的纹理。”

                  【讨论】:

                    【解决方案19】:

                    在 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"
                    }
                    

                    【讨论】:

                      【解决方案20】:

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

                      【讨论】:

                      • 请不要遵循此解决方案,它可能会起作用,但代价是在较新版本的 Android 的兼容模式下运行您的应用程序。
                      猜你喜欢
                      • 1970-01-01
                      • 2017-09-15
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-02-24
                      • 1970-01-01
                      相关资源
                      最近更新 更多