很多App为了适配不同手机的通知栏配色而让自己定义的通知栏内容显示清楚使用了不同的自适应方案。一般是通过获取系统默认的通知的标题和内容颜色做文章。网上有很多获取的方法,但是对于不熟悉系统层的人有时候不清楚这个颜色到底是在哪里设置的,所以来一探究竟。
首先观察Notification.Builder用来创建通知视图的方法。
//\frameworks\base\core\java\android\app\Notification.java
/**
* Construct a RemoteViews for the final 1U notification layout. In order:
* 1. Custom contentView from the caller
* 2. Style's proposed content view
* 3. Standard template view
*/
public RemoteViews createContentView() {
if (mN.contentView != null && (mStyle == null || !mStyle.displayCustomViewInline())) {
return mN.contentView;
} else if (mStyle != null) {
final RemoteViews styleView = mStyle.makeContentView();
if (styleView != null) {
return styleView;
}
}
// 若没有自定义的布局和style,则使用标准模板,也就是默认布局
return applyStandardTemplate(getBaseLayoutResource());
}
然后在找到加载系统默认通知布局的方法,发现其布局文件为notification_template_material_base.xml。
//\frameworks\base\core\java\android\app\Notification.java
private int getBaseLayoutResource() {
return R.layout.notification_template_material_base;
}
于是我们找到这个布局文件,并在其中找到显示通知内容的布局notification_template_part_line1.xml。
<!--\frameworks\base\core\res\res\layout\notification_template_material_base.xml-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="base"
>
<include layout="@layout/notification_template_header" />
<LinearLayout
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginStart="@dimen/notification_content_margin_start"
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_content_margin_top"
android:layout_marginBottom="@dimen/notification_content_margin_bottom"
android:orientation="vertical"
>
<!-- 显示通知内容的布局 -->
<include layout="@layout/notification_template_part_line1" />
<include layout="@layout/notification_template_text" />
</LinearLayout>
...
</FrameLayout>
所以继续查看notification_template_part_line1.xml。
<!--\frameworks\base\core\res\res\layout\notification_template_part_line1.xml-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<!-- 默认通知标题 -->
<TextView android:id="@+id/title"
android:textAppearance="@style/TextAppearance.Material.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
/>
<!-- 默认通知内容 -->
<TextView android:id="@+id/text_line_1"
android:textAppearance="@style/TextAppearance.Material.Notification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end|bottom"
android:layout_marginStart="16dp"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
/>
</LinearLayout>
于是我们发现,控制默认通知标题和内容的style就是TextAppearance.Material.Notification.Title和TextAppearance.Material.Notification。那么就来看看这两style,他们在colors_material.xml文件中被定义。
<!--\frameworks\base\core\res\res\values\colors_material.xml-->
<style name="TextAppearance.Material.Notification">
<item name="textColor">@color/secondary_text_material_light</item>
<item name="textSize">@dimen/notification_text_size</item>
</style>
<style name="TextAppearance.Material.Notification.Title">
<item name="textColor">@color/primary_text_default_material_light</item>
<item name="textSize">@dimen/notification_title_text_size</item>
</style>
到这里我们就可以知道默认通知的标题和内容的颜色分别是secondary_text_material_light和primary_text_default_material_light。因为这是系统根据自己背景默认设置的颜色,所以在不同的系统上都会与背景有很大的反差,会显示的清楚。因此,根据这两个颜色我们就可以为自己的通知设置自适应的颜色而不会由于颜色相近显示不出。但具体自适应的值会根据不同的算法而不同。
最后列出系统默认通知背景颜色是哪个值控制。
<!--\frameworks\base\core\res\res\values\colors.xml-->
<color name="notification_material_background_color">#ffffff</color>