To ensure your notification looks its best across different versions of Android, you should always use the standard notification template to build your notification. However, if the system templates do not meet your needs, you can provide your own layout for the notification.
If you want to provide more content in your notification, also consider using one of the expandable notification templates instead of building a custom layout.
Caution: When you use a custom notification layout, take special care to ensure that your custom layout works with different device orientations and resolutions. While this advice applies to all UI layouts, it's especially important for notifications because the space in the notification drawer is very restricted. The height available for a custom notification layout depends on the Android version. On some versions, collapsed view layouts are limited to as little as 48 dp, heads up view layouts are limited to as little as 88dp, and expanded view layouts are limited to as little as 252 dp.
Create custom layout for the content area
If you need a custom layout, you can apply
NotificationCompat.DecoratedCustomViewStyle
to your notification. This API allows you to provide a custom layout for the
content area normally occupied by the title and text content,
while still using system decorations for the
notification icon, timestamp, sub-text, and action buttons.
This API works similarly to the expandable notification templates by building upon the basic notification layout as follows:
- Build a basic notification
with
NotificationCompat.Builder
. - Call
setStyle()
, passing it an instance ofNotificationCompat.DecoratedCustomViewStyle
. - Inflate your custom layout as an instance of
RemoteViews
. Call
setCustomContentView()
to set the layout for the collapsed notification.Optionally, also call
setCustomBigContentView()
to set a different layout for the expanded notification.
For example:
Kotlin
// Get the layouts to use in the custom notification val notificationLayout = RemoteViews(packageName, R.layout.notification_small) val notificationLayoutExpanded = RemoteViews(packageName, R.layout.notification_large) // Apply the layouts to the notification val customNotification = NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .setCustomContentView(notificationLayout) .setCustomBigContentView(notificationLayoutExpanded) .build()
Java
// Get the layouts to use in the custom notification RemoteViews notificationLayout = new RemoteViews(getPackageName(), R.layout.notification_small); RemoteViews notificationLayoutExpanded = new RemoteViews(getPackageName(), R.layout.notification_large); // Apply the layouts to the notification Notification customNotification = new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setStyle(new NotificationCompat.DecoratedCustomViewStyle()) .setCustomContentView(notificationLayout) .setCustomBigContentView(notificationLayoutExpanded) .build();
Beware that the background color for the notification can vary across different
devices and versions. So you should always apply support library styles such as
TextAppearance_Compat_Notification
for the text and
TextAppearance_Compat_Notification_Title
for the title in your custom layout. These styles adapt to the color variations
so you don't end up with black-on-black or white-on-white text. For example:
<TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="@string/notification_title" android:id="@+id/notification_title" style="@style/TextAppearance.Compat.Notification.Title" />
Also avoid setting a background image on
your RemoteViews
object, because your text color may
become unreadable.
Create a fully custom notification layout
If you don't want your notification decorated with the standard notification
icon and header, follow the steps above but do not call setStyle()
.
To support Android versions older than Android 4.1 (API level 16), you
should also call setContent()
,
passing it the same RemoteViews
object.