Android Adaptive Icons
One of the worst experiences as an Android user is when you install an app, add it to your home screen and you realize it doesn't support adaptive icons. That invariably overly colorful square icon sticks out like a sore thumb and is often quickly uninstalled. Let's learn how you can adopt Adaptive Icons in your app to give your users the best experience.
Shape Adaptive Icons #
The first support you should adopt is shape adaptive icons which allow the OS to change the clipped shape of the icon background and add relevant animations on the icon when the user interacts with it. We support this by defining the icon as two layers, a "foreground" and a "background". The "foreground" is a drawable and the "background" can be defined by a drawable or by a color resource. Each layer should be 108x108 dp but the "foreground" icon should be between 48x48 dp and 72x72 dp and centered in the drawable to ensure it appears correctly inside the masked viewport.
Theme Adaptive Icons #
The next support you should adopt is theme adaptive icons which allows the OS to change the color of the icon to match the user's current theme color. This is done by providing an additional "monochrome" layer in our adaptive icon. This drawable has the same restrictions as the "foreground" layer icon, the layer should be 108x108 dp and the icon should be between 48x48 dp and 72x72 dp and centered in the drawable. This drawable could be the same as your "foreground" layer depending on the complexity of your icon.
Adopting Adaptive Icons in your App #
For this next section we are going to assume we've created the necessary assets and we'll add adaptive icon support into the app. We will do this using Asset Studio which has several benefits over adding the files manually including previewing your icon and the ability to generate legacy icons at the same time. If you already have a shape adaptive icon in your app, feel free to jump to the Adding Theme Adaptive Icon Support section. For this walkthrough I'm using Android Studio Hedgehog 2023.1.1. There may be differences, especially in Asset Studio, if you are using a different version.
Adding an Adaptive Icon #
To set up our adaptive icon using Asset Studio
- Right click on the "res" directory and select "New" -> "Image Asset". This will open the "Configure Image Asset" dialog
- Ensure the "Icon type:" is set to "Launcher Icons (Adaptive and Legacy)"
- Name the icon whatever you want, we will use the default "ic_launcher"
- For the "Foreground Layer" tab select our Source Asset and adjust the Scaling as desired, use the preview to ensure our icons look as expected
- Switch to the "Background Layer" tab and select our Source Asset and adjust the Scaling as desired.
- Continue to the "Options" tab and adjust the settings if needed
- Finally, click "Next" and then "Finish"
We should now see a file named ic_launcher.xml
in the res/mipmap
directory. Opening the file should look like this.
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
Now, confirm our icon has been added to our AndroidManifest.xml
file in the application tag.
<application
...
android:icon="@mipmap/ic_launcher"
Our app now supports shape adaptive icons! In the next section we will add support for theme adaptive icons as well.
Adding Theme Adaptive Icon Support #
Go to the ic_launcher.xml
file in res/mipmap
directory and add a new element called monochrome
inside the <adaptive-icon>
element and set the android:drawable
attribute to the monochrome drawable we want for our theme adaptive icon. The file will now look like the following.
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>
That's it, our app is now ready to support both shape and theme adaptive icons!
Additional Tips #
- Shortcuts - The same strategy for supporting adaptive app icons works for supporting adaptive shortcut icons. For static drawable shortcut icons use the
<adaptive-icon>
element and for dynamic shortcuts usecreateWithAdaptiveBitmap()
- Delete
android:roundIcon
from the manifest - To support theme adaptive icons, remove support for a "roundIcon". This was only needed on API level 25 and will fallback to the legacy icon if not present. Having theroundIcon
property set in the manifest will cause theme adaptive icons to not show up correctly. - Monochrome Icons and Transparency - Beware of using multiple colors in the monochrome drawable. When rendered, all colors will be set to the monochrome color. The only exception to this, is that the alpha channel will be kept.
- API Level Support - Shape adaptive icons have had support since Android 8.0 Oreo (API level 26) while theme adaptive icons are much newer and are supported on Android 13 (API level 33) and newer.
- Respecting Branding - Brands are rightly protective of their colors, so consider thinking outside the box when adding support for theme adaptive icons. One of my personal favorites is the Starbucks app which replaces the iconic siren logo with the image of a coffee cup for their "monochrome" drawable.
Bring it all together #
We're now ready to add adaptive icons to your app. We've seen how to add support for both shape and theme adaptive icons, the guidelines for creating those assets, and some additional tips for adopting adaptive icons. I hope you will take this opportunity to give users the personalized experience they expect on Android. Until next time, thanks!
Did you find this content helpful?
Please share this post and be sure to subscribe to the RSS feed to be notified of all future articles!
Want to go above and beyond? Help me out by sending me $1 on Ko-fi. It goes a long way in helping run this site and keeping it advertisement free. Thank you in advance!
- Previous: semantics Vs clearAndSetSemantics
- Next: Dev Diary - July 2023