Skip to main content

How to Create a Custom Notification Layout in Android Using Kotlin

Custom Notification Layout Android
How to Create a Custom Notification Layout in Android Using Kotlin

How to Create a Custom Notification Layout in Android Using Kotlin

In the world of Android development, notifications play a crucial role in engaging users. But standard notifications often look generic and can sometimes fail to capture the user’s attention effectively. Creating a custom notification layout lets you design notifications that are more interactive, visually striking, and aligned with your app's branding.

In this comprehensive guide, we'll walk you through the step-by-step process of creating a custom notification layout in Android using Kotlin. Whether you want to add images, buttons, or a unique arrangement of views in your notification, this post will help you accomplish it with detailed explanations and practical code examples.

Why Use Custom Notifications?

Standard Android notifications are useful but limited in design and interaction. Custom notifications, built with RemoteViews, allow you to:

  • Incorporate your own layout design — colors, text styles, and images.
  • Include interactive elements like buttons or toggles.
  • Deliver more engaging content tailored to the user's context.
  • Maintain consistent branding across all touchpoints.

All these result in a better user experience and can improve your app's engagement rates.

Prerequisites

  • Basic knowledge of Kotlin and Android Studio
  • Familiarity with Android notifications and layouts
  • Android device or emulator running API level 21+ (Lollipop and above recommended)

Step 1: Create the Layout XML for the Custom Notification

The first step is to create a custom layout XML file that will be inflated into the notification using RemoteViews. Custom notification layouts are usually quite simple due to size constraints but can be styled according to your needs.

Android Notification Structure

Understanding the components of an Android notification.

Create a new layout resource file called custom_notification.xml in the res/layout directory with the following content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="16dp"
    android:background="@color/notification_bg">

    <ImageView
        android:id="@+id/image"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/ic_launcher_foreground"
        android:contentDescription="@string/notification_image" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingStart="12dp">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Custom Notification Title"
            android:textColor="@android:color/black"
            android:textStyle="bold"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="This is a custom notification layout"
            android:textColor="@android:color/darker_gray"
            android:textSize="14sp" />

    </LinearLayout>

</LinearLayout>

This simple layout contains an image on the left and a vertical stack of title and text on the right.

Step 2: Setting Up the Notification Channel (Android 8.0+)

Since Android Oreo (API level 26), notification channels are required to display notifications. You need to create a channel before posting notifications, or else your notifications won’t show.

private fun createNotificationChannel(context: Context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = "custom_notification_channel"
        val channelName = "Custom Notifications"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(channelId, channelName, importance).apply {
            description = "Channel for custom notifications"
        }

        val notificationManager: NotificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Make sure to call this method once, typically in your Application class or before posting the notification.

Step 3: Building the Custom Notification in Kotlin

Now that the layout and channel are ready, let's build the notification using RemoteViews and NotificationCompat.Builder.

fun showCustomNotification(context: Context) {
    val channelId = "custom_notification_channel"
    createNotificationChannel(context)

    // Inflate the custom notification layout
    val remoteViews = RemoteViews(context.packageName, R.layout.custom_notification).apply {
        setTextViewText(R.id.title, "Hello from Kotlin!")
        setTextViewText(R.id.text, "This is your custom notification with a tailored layout.")
        setImageViewResource(R.id.image, R.drawable.ic_notifications)
    }

    // Create an explicit intent for an activity in your app
    val intent = Intent(context, MainActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val pendingIntent = PendingIntent.getActivity(
        context, 0, intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    val builder = NotificationCompat.Builder(context, channelId)
        .setSmallIcon(R.drawable.ic_notification_small)
        .setStyle(NotificationCompat.DecoratedCustomViewStyle())
        .setCustomContentView(remoteViews)
        .setCustomBigContentView(remoteViews) // Optional: same layout for expanded notification
        .setContentIntent(pendingIntent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setAutoCancel(true)

    val notificationManager = NotificationManagerCompat.from(context)
    notificationManager.notify(1001, builder.build())
}

Let's break down the key points:

  • We create a RemoteViews object by referencing our custom layout and update its views programmatically using methods like setTextViewText and setImageViewResource.
  • The notification must have a small icon, or it won't show properly.
  • NotificationCompat.DecoratedCustomViewStyle() makes sure the notification displays well on different devices.
  • We attach a PendingIntent so tapping the notification opens an activity.
  • setCustomContentView sets the collapsed notification view; you can also optionally define setCustomBigContentView for the expanded view.

Step 4: Handling Actions in Custom Notification (Optional)

If you want your custom notification layout to include actionable buttons (like "Reply", "Mark as Read", etc.), you need to add clickable views to your layout and assign PendingIntents to those views programmatically.

Add buttons in your custom_notification.xml layout:

<Button
    android:id="@+id/button_action"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Open App"
    android:textColor="@color/white"
    android:backgroundTint="@color/colorPrimary"
    android:minWidth="72dp"
    android:minHeight="36dp"
/>

Set a click handler in your notification setup:

val buttonIntent = Intent(context, YourBroadcastReceiver::class.java).apply {
    action = "com.yourapp.ACTION_BUTTON_CLICK"
}
val buttonPendingIntent = PendingIntent.getBroadcast(
    context, 0, buttonIntent,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

remoteViews.setOnClickPendingIntent(R.id.button_action, buttonPendingIntent)

You then handle this action inside YourBroadcastReceiver, which allows you to respond to button clicks directly from the notification.

Step 5: Testing Your Custom Notification

To verify your custom notification works correctly:

  • Run the app on a physical device or emulator.
  • Trigger the showCustomNotification() method (e.g., from a button click or on app start).
  • Inspect the notification shade to see your custom design.
  • Interact with any buttons if implemented.
  • Test on different Android versions to ensure compatibility.

Best Practices and Tips

  • Keep layouts simple: Notifications have limited space and should remain concise.
  • Use vector drawables: For sharp images on all screen densities.
  • Respect Do Not Disturb: Use appropriate notification importance and avoid intrusive designs.
  • Test on multiple devices: Custom views may render differently on OEM skins.
  • Follow accessibility guidelines: Ensure text is readable and elements are properly labeled.

Conclusion

Custom notifications are a powerful tool in Android development that allow you to go beyond the default UI, crafting richer user experiences tailored to your app’s needs. Using Kotlin and RemoteViews, creating these highly customizable notifications is straightforward once you understand the core concepts.

We've covered creating a custom notification layout XML, setting up notification channels, building and displaying the notification with Kotlin code, and even adding interactive buttons. Implement these practices to make your app’s notifications more engaging and useful.

Stay up to date with Android’s evolving notification APIs to leverage new features and deliver the best experience for your users.

RemoteViews for Custom Layouts

Happy coding!

Comments

Popular posts from this blog

How to Download Apk file from Url and Install Programmatically

In this post we learn about download apk file from server or website and then install it Programmatically in Phone. Sometimes we have to download external apk file from server and then install if downloading successfully finished.For this we use AsyncTask class  for background process. So here is Code Snippet for this task.Lets Start :- Before this we have to add these Permissions in Manifest.xml file : <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> DownloadNewVersion.java class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> { @Override protected void onPreExecute() { super.onPreExecute(); bar = new ProgressDialog(getActivity()); bar.setCancelable(false); bar.setMessage("Downl...

Working with Android 11 (Changes and Security Features)

 Hello everyone , I am here with new article which is hot topic nowadays "Android 11" .The stable version of Android.  Android 11 is the eleventh major release and 18th version of Android, the mobile operating system developed by the Open Handset Alliance led by Google. It was released on September 8, 2020.It is comes with many security features and other features as well . And it is now compulsory in play store  to upload new apps with API lavel 30 which is compatible with Android 11 and from November onwards old apps also have to update with API 30 .Some other guidelines you can check out from here . Play Store Guidelines So its clear that we have to update our apps with API level 30 .But Android 11 comes with some changes as well which we have to do in our projects. For example from Android developer site "Android 11 (API level 30) further enhances the platform, giving better protection to app and user data on external storage. ". Scoped storage enforcement: Apps...

How to sort a list in ascending order and Add header by the first letter in the RecyclerView in Android

Hello Forks ! Hope you are doing well. In this tutorial we will understand how to sort a list of data, it could be any data like bank names , places names etc. in ascending order with a header which grouped the same type of data under it. For example we have a list of banks data and we want to group all banks starting with 'A' character in single unit and so on. So without taking too much time  let's move to the coding part and understand how we can achieve this. Step 1 : Create a Model class Named Bank.java public class Bank { private String name; public Bank (String name) { this .name = name; } public String getName () { return name; } } Step 2 : Sort the List of Banks with this Method import java.util.Collections; import java.util.Comparator; import java.util.List; public void sortBankList (List<Bank> bankList) { Collections.sort(bankList, new Comparator <Bank>() { @Override pub...