I want to show a notification for a message in my app. In previous versions of Android everything is ok, but in Lollipop the notification background is white.
I used this XML code for my notification layout in layout_message_notification.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_messageNotification"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent">
<LinearLayout
android:layout_width="0dp"
android:layout_weight=".2"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/message_icon"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight=".8"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<TextView
android:id="@+id/textView_notification_title"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="right|center_vertical"
android:layout_margin="15dp"/>
</LinearLayout>
</LinearLayout>
My notification in lollipop is shown like this:
How can I make the notification background dark or transparent, like in previous versions of Android?
call setColor -> the color to be used on the background. call setColorized -> the actual call to set the background color. set style to NotificationCompat. DecoratedMediaCustomViewStyle()
1 Tap Notification Settings on the notification panel or tap the Settings app. 2 Tap Notifications. 3 Tap App icon badges.
This answer describes a hacky method of changing of notification background color.
Pay attention: this is an undocumented workaround; it is based on reflection and may be broken on custom firmwares; it is applicable to Android Lollipop and Marshmallow versions only; it will not work on Android N and higher versions. I would recommend to stick with the default color unless you have a serious reason to avoid it.
WHY
There is no legal way to set a background color for the custom notification. Google decided that notifications must be white or light gray depending on its priority according to Material Design. However, Google also made two exceptions to this rule:
MediaStyle
can be of ANY color.As a result of the second exception, such limitation looks illogical and unreasoned, and that is the only possible excuse why you still want to use a custom color instead of the one that is recommended (or forced?) by Google.
WHAT'S INSIDE
Lets look into BaseStatusBar
to see how this limitation is imposed. The only place where the background color for the notification is calculated is applyColorsAndBackgrounds method.
First branch of the if
statement is for legacy applications. The only way to get here is to set the target SDK of your application below Build.VERSION_CODES.LOLLIPOP
. The background will be turned black in this case.
We are interested in the entry.row.setTintColor
statement. To reach it, several checks should be passed, including the one contained within isMediaNotification method. Here they are:
com.android.internal.R.id.status_bar_latest_event_content
as its ID.com.android.internal.R.id.media_actions
as its ID.HOW
The most problematic are IDs as long as they are declared in the internal resources and cannot be accessed from the application's layout XML.
The second problem is that the RemoteViews
used in the notification is just an ID of the layout resource within the application and cannot be constructed in the code. As a result, we cannot add layouts with IDs required to pass all the checks mentioned above.
However, Google added the addView
and removeAllViews
methods into RemoteViews
for their needs (they are used in the MediaStyle
notification) and forgot to make them private.
So, the final idea is simple:
removeAllViews
addView
media_actions
to invisible view inside of our custom layout (to pass the 3rd check)Drawbacks:
SOLUTION
Our custom big view must contain FrameLayout
with android.R.id.empty
as its ID. Actually, any ID may be used here, just make sure that you reference the same ID in code (see below).
// We need theese ids to use internal Android resources
int topId = Resources.getSystem().getIdentifier("status_bar_latest_event_content", "id", "android");
int topBigLayout = Resources.getSystem().getIdentifier("notification_template_material_big_media_narrow", "layout", "android");
int topSmallLayout = Resources.getSystem().getIdentifier("notification_template_material_media", "layout", "android");
RemoteViews viewSmall = ...; // Create our custom view here
RemoteViews viewBig = ...; // Create our custom big view here
// This is invisible inner view - to have media_actions in hierarchy
RemoteViews innerTopView = new RemoteViews("android", topBigLayout);
viewBig.addView(android.R.id.empty, innerTopView);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topBigView = new RemoteViews("android", topBigLayout);
topBigView.removeAllViews(topId);
topBigView.addView(topId, viewBig);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topSmallView = new RemoteViews("android", topSmallLayout);
topSmallView.removeAllViews(topId);
topSmallView.addView(topId, viewSmall);
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.drawable.ic_notification)
.setTicker("Some text")
.setColor(0xff000000) // The desired color!
.setContent(topSmallView);
Notification n = builder.build();
n.bigContentView = topBigView;
// Use our notification "n" here as usual
It is possible to use another layout instead of notification_template_material_big_media_narrow
on the top level to manipulate the height of the big view. Search for appropriate one here among notification_template_xxx.xml files. But do not forget about putting media_actions
into hierarchy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With