Implement adaptive icons

Adaptive Icons maintain a consistent shape intra-device but vary from device to device with only one icon asset provided by the developer. Additionally, icons support two layers (foreground and background) that can be used for motion to provide visual delight to users.

Device implementers provide a device mask that will decide the shape of all icons on a device. This icon will be used on any system UI surfaces that use Launcher Icons (e.g., launcher, overview, settings and share sheet).

Examples and source

Code examples:

  • platform/development/samples/AdaptiveIconSample/

Developer documentation:

Source code:

  • platform/frameworks/base/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java

Implementation

To change the shape of the icon on a platform, overlay one string in framework/base/core/res/res/values/config.xml, as follows:

<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
    <string name="config_icon_mask" translatable="false">"M50,0L100,0 100,100 0,100 0,0z"</string>

The format and syntax of the string follow the W3, SVG standard for path definition. This format for PathData is what Android vector drawables support as well.

This path should be convex and should respect the safezone (66/71 = 91%) within the view bounds. This is enforced in one of the CTS tests.

If you decide to use a circle as the platform mask, make sure to also overlay config_useRoundIcon = true. If not, set this config value false or do not specify this config value.

Adaptive Icon API

The API for the AdaptiveIconDrawable class is shown below:

package  android.graphics.drawable;
    public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
    method public Drawable getBackground();
    method public Drawable getForeground();
    method public Path getIconMask();
    method public Region getSafeZone();
    method public float getExtraInsetFraction();
    method public int getOpacity();
    method public void invalidateDrawable(Drawable);
    method public void scheduleDrawable(Drawable, Runnable, long);
    method public void setAlpha(int);
    method public void setColorFilter(ColorFilter);
    method public void setOpacity(int);
    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
    }
public class Icon extends Parceleable {
    method public Bitmap createWithAdaptiveBitmap();
    }

Reference implementation

Nothing needs to be done to render the static adaptive icons on any of the System UI surfaces. When PackageManager returns a drawable, simply bind that to an ImageView. This is how icons are already rendered in Pre-O platforms.

Regarding rendering dynamic motion effect, Launcher3 (platform/packages/apps/Launcher3) will have a reference implementation showing how to achieve the effect in O-MR1.

Validation

To validate the implementation, after overriding the mask of their liking, see if icons are rendered correctly in Launcher3, Settings, Overview and Settings. You may also run AdaptiveIconDrawableTest.java and AdaptiveIconMaskTest.java inside graphics CTS TestCase to test the implementation.

A recommended manual test case can be found at: platform/development/samples/AdaptiveIconSample/.

Known issues

Known issues include the following:

  • Blurry icons, depending on how the mask path is defined.
  • Zoomed-in shortcut icons if app developers do not use the Icon.createWithAdaptiveBitmap() method, or do not use this method properly. For this method to function properly, the passed in Bitmap should be padded 25% on all four sides.

These issues can be addressed as follows:

  • The mask should be defined in [0, 100] x [0, 100] coordinate system.
  • Make sure that images used for adaptive icons (launcher icons , shortcuts) have sufficient padding (25%) on all four sides.