自定义通知布局和文字颜色

我的应用程序显示一些通知,并根据用户的喜好,它可能会使用通知中的自定义布局。 它运作良好,但有一个小问题 – 文字颜色 。 股票Android和几乎所有的制造商皮肤使用黑色文本对通知文本的浅色背景,但三星不:他们的通知下拉有一个黑暗的背景,默认通知布局中的文本是白色的。

所以这会导致一个问题:不使用任何花哨布局的通知显示正常,但是使用自定义布局的通知很难阅读,因为文本是黑色的,而不是默认的白色。 即使官方文档只是为TextView设置#000颜色,所以我找不到任何指针。

一个用户很友善地截取了这个问题的截图:

截图

那么如何在我的布局中使用设备的默认通知文字颜色 ? 我宁愿不动手改变基于手机型号的文本颜色,因为这需要大量的更新,而使用自定义ROM的人可能仍然会遇到问题,这取决于他们使用的皮肤。

Malcolm的解决scheme在API> = 9的情况下工作良好。 以下是旧API的解决scheme:

诀窍是创build标准通知对象,然后遍历由Notification.setLatestEventInfo(...)创build的默认contentView 。 当您find正确的TextView时,只需获取tv.getTextColors().getDefaultColor()

以下是提取默认文本颜色和文本大小的代码(按比例缩放密度像素 – sp)。

 private Integer notification_text_color = null; private float notification_text_size = 11; private final String COLOR_SEARCH_RECURSE_TIP = "SOME_SAMPLE_TEXT"; private boolean recurseGroup(ViewGroup gp) { final int count = gp.getChildCount(); for (int i = 0; i < count; ++i) { if (gp.getChildAt(i) instanceof TextView) { final TextView text = (TextView) gp.getChildAt(i); final String szText = text.getText().toString(); if (COLOR_SEARCH_RECURSE_TIP.equals(szText)) { notification_text_color = text.getTextColors().getDefaultColor(); notification_text_size = text.getTextSize(); DisplayMetrics metrics = new DisplayMetrics(); WindowManager systemWM = (WindowManager)getSystemService(Context.WINDOW_SERVICE); systemWM.getDefaultDisplay().getMetrics(metrics); notification_text_size /= metrics.scaledDensity; return true; } } else if (gp.getChildAt(i) instanceof ViewGroup) return recurseGroup((ViewGroup) gp.getChildAt(i)); } return false; } private void extractColors() { if (notification_text_color != null) return; try { Notification ntf = new Notification(); ntf.setLatestEventInfo(this, COLOR_SEARCH_RECURSE_TIP, "Utest", null); LinearLayout group = new LinearLayout(this); ViewGroup event = (ViewGroup) ntf.contentView.apply(this, group); recurseGroup(event); group.removeAllViews(); } catch (Exception e) { notification_text_color = android.R.color.black; } } 

调用extractColors即。 在你的服务的onCreate()。 然后,当您创build自定义通知时,您需要的颜色和文本大小位于notification_text_colornotification_text_size

 Notification notification = new Notification(); RemoteViews notification_view = new RemoteViews(getPackageName(), R.layout.notification); notification_view.setTextColor(R.id.label, notification_text_color); notification_view.setFloat(R.id.label, "setTextSize", notification_text_size); 

解决scheme是使用内置的样式。 您需要的样式在Android 2.3和Android 4.x中称为TextAppearance.StatusBar.EventContent 。 在Android 5.x素材通知中,使用其他几种样式: TextAppearance.Material.NotificationTextAppearance.Material.Notification.TitleTextAppearance.Material.Notification.Line2 。 只需为文本视图设置适当的文本外观,您将获得必要的颜色。

如果你对我是如何到达这个解决scheme感兴趣的话,这里是我的痕迹。 代码摘录取自Android 2.3。

  1. 当您使用Notification并通过使用内置手段设置文本时,下面的行创build布局:

     RemoteViews contentView = new RemoteViews(context.getPackageName(), com.android.internal.R.layout.status_bar_latest_event_content); 
  2. 提到的布局包含以下View ,它负责查看通知文本:

     <TextView android:id="@+id/text" android:textAppearance="@style/TextAppearance.StatusBar.EventContent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:singleLine="true" android:ellipsize="marquee" android:fadingEdge="horizontal" android:paddingLeft="4dp" /> 
  3. 所以结论是所需的样式是TextAppearance.StatusBar.EventContent ,其定义如下所示:

     <style name="TextAppearance.StatusBar.EventContent"> <item name="android:textColor">#ff6b6b6b</item> </style> 

    你应该在这里注意到这个样式实际上并没有引用任何内置的颜色,所以最安全的方法是应用这种样式而不是内置的颜色。

还有一件事:在Android 2.3(API Level 9)之前,既没有样式也没有颜色,只有硬编码的值。 如果由于某种原因您碰巧需要支持这些旧版本,请参阅Gaks的答案 。

这里是仅使用资源的任何SDK版本的解决scheme。

RES /值/ styles.xml

 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="NotificationTitle"> <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> <item name="android:textStyle">bold</item> </style> <style name="NotificationText"> <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> </style> </resources> 

RES /值-V9 / styles.xml

 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" /> <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" /> </resources> 

RES /布局/ my_notification.xml

 ... <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="title" style="@style/NotificationTitle" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="text" style="@style/NotificationText" /> ... 

PS:硬编码值用于2.2-。 因此,一些罕见的旧定制固件可能会出现问题。

对于2.3+(来自Android文档 ):

主要文本使用样式android:TextAppearance.StatusBar.EventContent.Title

为辅助文本使用样式android:TextAppearance.StatusBar.EventContent

对于2.2-,按照Gaks在另一个回答这个主题的build议做什么。

如果你想编译2.2并支持2.3+,并且支持所有各种设备,Gaks的解决scheme是我所知道的唯一的解决scheme。

顺便说一句,谷歌build议使用的价值?android:attr/textColorPrimary为2.2,不起作用。 只需使用模拟器来尝试。 Gaks的方式是唯一的方法。

更多的资源: 这和这是行不通的。

你应该使用android.R.color指定的颜色

例如: android.R.color.primary_text_light

自定义ROM开发人员和Android皮肤devise师应该更新这些,以便您的应用程序的颜色可以与系统的其他部分保持一致。 这包括确保您的文本在整个系统中正确显示。

我发现了一个非常简单的解决scheme,直接更改Android提供的属性的名称。

正如您在本教程中所看到的: http : //www.framentos.com/android-tutorial/2012/02/20/how-to-create-a-custom-notification-on-android/

你只需要使用不同的属性:

 <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> 

希望这可以帮到你!

看看这个指示: http : //developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView如果你设置你的LinearLayout容器的背景颜色,那么你可以有你的颜色通知文本和的背景。

如果通知文本的默认颜色是由启动程序应用程序定义的,那么您将无法从android默认设置中检索它,除非启动程序正在分割这些信息。

但是,你有尝试从你的布局中删除这行android:textColor =“#000”,以便它可以自动获得默认的颜色?

由于TextAppearance.Material.Notification.Title是系统硬编码颜色,来自@Malckom的解决scheme没有帮助我在黑暗的通知背景的Lolipop。 来自@grzaks的解决scheme做了,但在通知创build过程中进行了一些更改:

 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setContentTitle(NOTIFICATION_TITLE_TIP) .setContentText(NOTIFICATION_TEXT_TIP); Notification ntf = mBuilder.build(); // ... if (NOTIFICATION_TEXT_TIP.equals(szText)) { notification_text_color = text.getTextColors().getDefaultColor(); } else { if (NOTIFICATION_TITLE_TIP.equals(szText)) { notification_title_color = text.getTextColors().getDefaultColor(); } } // ... 

我知道这是一个古老的问题,但它可以帮助别人; )我在我的应用程序中这样做,并在几行完美的作品:

  RemoteViews notificationView = new RemoteViews(context.getPackageName(), R.layout.notification_layout); if (SDK >= LOLLIPOP) { TextView textView = new TextView(context); textView.setTextAppearance(context, android.R.style.TextAppearance_Material_Notification_Title); notificationView.setTextColor(R.id.title, textView.getCurrentTextColor()); notificationView.setFloat(R.id.title, "setTextSize", textView.getTextSize()); textView.setTextAppearance(context,android.R.style.TextAppearance_Material_Notification_Line2); notificationView.setTextColor(R.id.contentText,textView.getCurrentTextColor()); notificationView.setFloat(R.id.contentText,"setTextSize",textView.getTextSize()); textView = null; }