Tom
Tom

Reputation: 203

How to implement themed icons by Material You in my Android App?

I can't find anything about that online, no documentation, nothing. Maybe one of you know how to do it or have got some advice for me. Thank you in advance.

Upvotes: 18

Views: 9243

Answers (2)

Bash
Bash

Reputation: 1628

Adding my solution as the accepted answer got me close, it was missing some info that I needed to get it working.

All I had to do was:

  1. Create the monochrome version of your icon

Just open the image in an image editor and remove all colour from the icon. You can Google how to do that according to the image editor you're using. It's recommended to make it completely black, but I made mine with 2 shades of gray and it worked fine. Mind you it only appears as 1 shade. By the way, I actually did this for each icon in my mipmap folders so they were each the correct size and everything. My icon is a png.

If yours is an SVG, you can just edit it like a text file and remove the fill and stroke colours until everything is black.

  1. Copy the monochrome icons to each mipmap folder under app/src/main/res

I named the icons ic_launcher_monochrome.png but you can technically name it whatever you want.

This includes: mipmap-hdpi, mipmap-ldpi, mipmap-mdpi, mipmap-xhdpi, mipmap-xxhdpi, mipmap-xxxhdpi I also did this for the mipmap-night-** folders.

For SVG's I believe you have to copy it to the drawable folders instead of mipmap.

  1. Update your ic_launcher.xml file(s) under mipmap-anydpi-v26

In my case, my file looks like this as I'm using Capacitor with the capacitor-assets package which generates my assets.

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background>
        <inset android:drawable="@mipmap/ic_launcher_background" android:inset="16.7%" />
    </background>
    <foreground>
        <inset android:drawable="@mipmap/ic_launcher_foreground" android:inset="16.7%" />
    </foreground>
    <monochrome>
        <inset android:drawable="@mipmap/ic_launcher_monochrome" android:inset="16.7%" />
    </monochrome>
</adaptive-icon>

But I think for most people it will look more like this:

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@mipmap/ic_launcher_background" />
    <foreground android:drawable="@mipmap/ic_launcher_foreground" />
    <monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon>

Remember to change @mipmap to @drawable if you're using an SVG.

If you have an ic_launcher_round.xml update it with the exact same code as well.

I also added both these files with the exact same code into mipmap-night-anydpi-v26 to support dark mode. I'm not actually sure if this is totally necessary, but it seems to work.

  1. Lastly, when testing, make sure you add the icon to the home screen

This tripped me for a while. Don't just check the icon in the apps dock, it needs to be on the home screen. If something still isn't working you can try reinstalling the app, but in my testing it was updating the icon without needing to reinstall. Also don't forget to enable Themed Icons in Android settings! Device must use Android 13+

Upvotes: 0

Oliver Spryn
Oliver Spryn

Reputation: 17368

Update on 02/18/2022: Android 13 has official support for themed icons. Just follow their steps here: https://developer.android.com/about/versions/13/features#themed-app-icons

To follow their example:

  1. Create a monochrome version of your app icon

  2. Add this to your ic_launcher.xml file, under the <adaptive-icon /> tagset:

    <adaptive-icon>
        <background android:drawable="..." />
        <foreground android:drawable="..." />
        <monochrome android:drawable="@drawable/myicon" />
    </adaptive-icon>
    
  3. Add your icon to your manifest:

    <application
        …
        android:icon="@mipmap/ic_launcher"
        …>
    </application>
    

Note: If android:roundIcon and android:icon are both in your manifest, you must either remove the reference to android:roundIcon or supply the monochrome icon in the drawable defined by the android:roundIcon attribute.

All of that was pulled directly from the Google developer's example.


There seems to be competing answers on this, but this issue on the Material Components GitHub repository seems to offer the most insight: https://github.com/material-components/material-components-android/issues/2357

Particularly, using an adaptive icon, like this:

<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <background android:drawable="@color/launcher_icon_background"/>

    <foreground>
        <aapt:attr name="android:drawable">
            <vector
                android:width="108dp"
                android:height="108dp"
                android:viewportWidth="108"
                android:viewportHeight="108">
                <path
                    android:fillColor="@color/launcher_icon"
                    android:pathData="m54,74.5l23.3,-29c-0.9,-0.7 -9.9,-8 -23.3,-8c-13.4,0 -22.4,7.3 -23.3,8l23.3,29l0,0c0,0 0,0 0,0zm7.7,-27.3c1.4,1.7 2.3,3.9 2.3,6.3l0,2l-20,0l0,-2c0,-2.4 0.9,-4.6 2.3,-6.3l-2.3,-2.3l1.4,-1.4l2.3,2.3c1.7,-1.4 3.9,-2.3 6.3,-2.3c2.4,0 4.6,0.9 6.3,2.3l2.3,-2.3l1.4,1.4l-2.3,2.3zm-9.7,4.3c0,1.1 -0.9,2 -2,2c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2c1.1,0 2,0.9 2,2zm8,0c0,1.1 -0.9,2 -2,2c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2c1.1,0 2,0.9 2,2z" />
                </vector>
        </aapt:attr>
    </foreground>
</adaptive-icon>

... with colors defined in colors.xml that refer to system-defined colors that derive from the Material 3 color pallet:

<resources>
    <color name="launcher_icon_background">@android:color/system_accent1_100</color>
    <color name="launcher_icon">@android:color/system_neutral1_800</color>
</resources>

Note that these colors derive from the system-defined pallet, as described in Material Design 3: https://m3.material.io/libraries/mdc-android/color-theming

You will likely have to create separate resource files that target API 31+ specifically. I have not tested out these recommendations.

Upvotes: 19

Related Questions