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

时间:2011-02-01 19:57:00

标签: android notifications android-notifications

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

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

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

Screenshot

所以如何在布局中使用设备中的默认通知文字颜色?我宁愿不开始根据手机型号动态改变文字颜色,因为这需要大量更新,而定制ROM的人可能仍会遇到问题,具体取决于他们正在使用的皮肤。

12 个答案:

答案 0 :(得分:80)

解决方案是使用内置样式。您需要的样式在Android 2.3和Android 4.x中称为TextAppearance.StatusBar.EventContent。在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>
    

    您应该注意,此样式实际上并未引用任何内置颜色,因此最安全的方法是应用此样式而不是某种内置颜色。

  4. 还有一件事:在Android 2.3(API Level 9)之前,既没有样式,也没有颜色,只有硬编码值。如果您因某些原因而不得不支持此类旧版本,请参阅answer by Gaks

答案 1 :(得分:58)

Malcolm的解决方案适用于API&gt; = 9。以下是旧API的解决方案:

诀窍是创建标准通知对象,然后遍历由contentView创建的默认Notification.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_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);

答案 2 :(得分:16)

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

  

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"
    />
...

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

答案 3 :(得分:13)

对于2.3+(来自Android documentation):

使用样式android:TextAppearance.StatusBar.EventContent.Title作为主要文字。

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

对于2.2-,在这个帖子的另一个答案中做Gaks suggested

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

BTW,谷歌建议将值?android:attr/textColorPrimary用于2.2-,是行不通的。只需使用模拟器进行尝试即可。 Gaks的方式是唯一的方式。

更多资源:Thisthis不起作用。

答案 4 :(得分:2)

您应该使用android.R.color

中指定的颜色

例如:android.R.color.primary_text_light

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

答案 5 :(得分:1)

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

如果启动器应用程序定义了通知文本的默认颜色,那么除非启动器正在分析此信息,否则无法从Android默认设置中检索它。

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

答案 6 :(得分: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>

希望这可以帮到你!

答案 7 :(得分:1)

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

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

如果背景是黑色,它会给我白色文本,如果背景是白色,则会给我黑色文本。而且至少可以追溯到API19。

答案 8 :(得分: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();
    }
}
// ...

答案 9 :(得分:0)

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

    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;

    }

答案 10 :(得分: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>

答案 11 :(得分:0)

在可扩展或折叠式布局中,将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文件中定义了黑白