Custom notification layouts and text colors
The solution is to use built-in styles. The style you need is called TextAppearance.StatusBar.EventContent
in Android 2.3 and Android 4.x. In Android 5.x material notifications use several other styles: TextAppearance.Material.Notification
, TextAppearance.Material.Notification.Title
, and TextAppearance.Material.Notification.Line2
. Just set the appropriate text appearance for the text view, and you will get the necessary colors.
If you are interested how I have arrived at this solution, here's my trail of breadcrumbs. The code excerpts are taken from Android 2.3.
When you use
Notification
and set the text by using built-in means, the following line creates the layout:RemoteViews contentView = new RemoteViews(context.getPackageName(), com.android.internal.R.layout.status_bar_latest_event_content);
The mentioned layout contains the following
View
which is responsible for viewing notification text:<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" />
So the conclusion is that the needed style is
TextAppearance.StatusBar.EventContent
, which definition looks like this:<style name="TextAppearance.StatusBar.EventContent"> <item name="android:textColor">#ff6b6b6b</item></style>
You should note here that this style doesn't actually reference any of the built-in colors, so the safest way is to apply this style instead of some built-in color.
One more thing: before Android 2.3 (API Level 9), there were neither styles, nor colors, there were only hard-coded values. If you happen to have to support such old versions for some reason, see the answer by Gaks .
Solution by Malcolm works fine with API>=9. Here's the solution for older API:
The trick is to create the standard notification object and then traverse the default contentView
created by Notification.setLatestEventInfo(...)
. When you find the right TextView, just get the tv.getTextColors().getDefaultColor()
.
Here's the code that extracts the default text color and text size (in scaled density pixels - 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; }}
Call extractColors
ie. in onCreate() of your service. Then when you're creating the custom notification, the color and text size you want are in notification_text_color
and 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);
Here is solution for any SDK version using only resources.
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" />...
P.S: Hard coded values are used for 2.2-. So problems can occur with some rare old custom firmwares.