82

我的应用程序显示了一些通知,并且根据用户偏好,它可能会在通知中使用自定义布局。它运行良好,但有一个小问题——文本颜色。普通的 Android 和几乎所有制造商的皮肤都使用黑色文本和浅色背景作为通知文本,但三星没有:他们的通知下拉菜单有深色背景,默认通知布局中的文本是白色的。

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

一位用户非常友好地截取了问题的屏幕截图:

截屏

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

4

12 回答 12

87

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

如果您对我是如何得出这个解决方案感兴趣的,这是我的面包屑痕迹。代码摘自 Android 2.3。

  1. 当您使用Notification内置方法使用和设置文本时,以下行将创建布局:

    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 级别 9)之前,既没有样式,也没有颜色,只有硬编码的值。如果您出于某种原因碰巧必须支持此类旧版本,请参阅Gaks 的答案

于 2011-02-08T15:50:46.310 回答
63

Malcolm 的解决方案适用于 API>=9。这是旧 API 的解决方案:

诀窍是创建标准通知对象,然后遍历contentViewNotification.setLatestEventInfo(...). 当您找到正确的 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() 中。然后,当您创建自定义通知时,您想要的颜色和文本大小位于notification_text_color和中notification_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);
于 2011-09-06T13:21:42.060 回答
17

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

res/values/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/values-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/layout/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-。因此,一些罕见的旧定制固件可能会出现问题。

于 2012-01-06T04:58:55.437 回答
13

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

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

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

对于 2.2-,按照Gaks在该线程的另一个答案中的建议进行操作。

如果您想针对 2.2 进行编译并支持 2.3+,并支持所有种类的设备,那么 Gaks 的解决方案是我所知道的唯一一个。

顺便说一句,谷歌建议使用?android:attr/textColorPrimary2.2- 的值是行不通的。只需使用模拟器尝试即可。Gaks的方式是唯一的方式。

更多资源:这个这个不起作用。

于 2011-12-06T19:21:39.507 回答
7

我在有问题的 TextView 上使用它:

style="@style/TextAppearance.Compat.Notification.Title"

如果背景是黑色,它会给我白色文本,如果背景是白色,它会给我黑色文本。它至少可以追溯到 API 19。

于 2018-08-25T10:17:17.003 回答
2

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

例如:android.R.color.primary_text_light

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

于 2011-02-02T02:40:27.460 回答
1

查看此说明: http: //developer.android.com/guide/topics/ui/notifiers/notifications.html#CustomExpandedView 如果您为 LinearLayout 容器设置背景颜色,那么您可以在文本通知中使用颜色和的背景。

如果通知文本的默认颜色是由启动器应用程序定义的,那么除非启动器共享此信息,否则您无法从 android 默认设置中检索它。

但是,您是否尝试从布局中删除此行 android:textColor="#000" 以便它可以自动获得默认颜色?

于 2011-02-06T05:34:04.363 回答
1

我找到了一个非常简单的解决方案,直接更改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>

希望这可以帮到你!

于 2012-02-21T18:49:59.217 回答
1

我知道这是一个老问题,但它可以帮助别人;)我在我的应用程序中执行此操作,并且在几行中效果很好:

    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;

    }
于 2017-01-01T22:38:32.077 回答
0

由于 TextAppearance.Material.Notification.Title 是系统硬编码颜色,@Malckom 的解决方案在通知背景较暗的 Lolipop 上没有帮助我。@grzaks 的解决方案确实如此,但在通知创建过程中进行了一些更改:

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();
    }
}
// ...
于 2016-03-05T12:51:25.127 回答
0

这是解决此错误的方法。将以下内容添加到 styles.xml

    <style name="TextAppearance">
    </style>
    <style name="TextAppearance.StatusBar">
    </style>
    <style name="TextAppearance.StatusBar.EventContent">
        <item name="android:textColor">#ff6b6b6b</item>
    </style>
    <style name="TextAppearance.StatusBar.EventContent.Info">
        <item name="android:textColor">#ff6b6b6b</item>
    </style>
于 2019-05-13T18:48:11.917 回答
-1

在您的可扩展或折叠布局中设置 android:background为,"@android:color/transparent"因为这会自动采用您的设备通知主题颜色并设置为背景

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_margin="0dp"
android:background="@android:color/transparent"
android:orientation="vertical">
          <TextView

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/colorSecondary"
            android:textStyle="bold" />

并且您的 textview 颜色定义为简单颜色文件中的文件中的黑白Resource/color以及夜间模式颜色文件

于 2020-09-29T09:22:18.350 回答