Как реализовать адаптивные значки

Адаптивные значки сохраняют одинаковую форму на одном устройстве, но могут выглядеть по-разному на разных устройствах. При этом разработчик предоставляет только один объект значка. Кроме того, значки поддерживают два слоя (передний и задний план), которые можно использовать для анимации, чтобы порадовать пользователей.

Производители устройств предоставляют маску, которая определяет форму всех значков на устройстве. Этот значок будет использоваться в интерфейсе системы, где применяются значки приложений (например, в Google Старт, обзоре, настройках и меню "Поделиться").

Примеры и источник

Примеры кода:

  • platform/development/samples/AdaptiveIconSample/

Документация для разработчиков:

Исходный код:

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

Реализация

Чтобы изменить форму значка на платформе, переопределите одну строку в framework/base/core/res/res/values/config.xml, как показано ниже.

<!-- 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>

Формат и синтаксис строки соответствуют стандарту W3, SVG для определения пути. Этот формат для PathData также поддерживается векторными объектами Android.

Путь должен быть выпуклым и находиться в безопасной зоне (66/71 = 91%) в пределах границ просмотра. Это требование проверяется в одном из тестов CTS.

Если вы решили использовать круг в качестве маски платформы, убедитесь, что также добавили наложение config_useRoundIcon = true. В противном случае задайте для этого параметра значение false или не указывайте его.

Adaptive Icon API

Ниже показан API для класса AdaptiveIconDrawable.

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();
    }

Пример реализации

Для отрисовки статических адаптивных значков на любых поверхностях системного интерфейса ничего делать не нужно. Когда PackageManager возвращает объект Drawable, просто привяжите его к ImageView. Именно так значки отображаются на платформах до версии O.

Что касается динамического эффекта движения, то в Launcher3 (platform/packages/apps/Launcher3) будет реализован пример, показывающий, как добиться этого эффекта в O-MR1.

Проверка

Чтобы проверить реализацию, после переопределения маски убедитесь, что значки правильно отображаются в Launcher3, настройках, режиме многозадачности и настройках. Чтобы проверить реализацию, вы также можете запустить AdaptiveIconDrawableTest.java и AdaptiveIconMaskTest.java в графическом CTS TestCase.

Рекомендуемый тестовый случай можно найти по адресу: platform/development/samples/AdaptiveIconSample/.

Известные проблемы

Известные проблемы:

  • Размытые значки (в зависимости от того, как определен путь маски).
  • Увеличенные значки ярлыков, если разработчики приложений не используют метод Icon.createWithAdaptiveBitmap() или используют его неправильно. Чтобы этот метод работал правильно, переданное изображение Bitmap должно иметь отступы 25% со всех четырех сторон.

Эти проблемы можно решить следующим образом:

  • Маска должна быть определена в системе координат [0, 100] x [0, 100].
  • Убедитесь, что у изображений, используемых для адаптивных значков (значков приложений, ярлыков), есть достаточные отступы (25%) со всех четырех сторон.