Подтвердить что ты не робот

Как пусковые установки меняют форму адаптивного значка, включая удаление фона?

Фон

Начиная с Android O, приложения могут иметь адаптивные значки, которые состоят из двух слоев чертежей: переднего плана и фона. Фон - это маска, которая становится формой выбора пусковой установки/пользователя, в то время как ОС также имеет форму по умолчанию.

Вот пример того, что позволяет Nova Launcher:

введите описание изображения здесь

Как вы можете видеть, это позволяет не только выбирать, какую форму использовать, но и вообще избегать фигуры (в "предпочитайте устаревшие значки" ).

Вот несколько ссылок об этом:

Проблема

Пока я знаю, как создать экземпляр AdaptiveIconDrawable, и я знаю мастера, который помогает создавая один для текущего приложения, я не понимаю, как, учитывая экземпляр AdaptiveIconDrawable, пусковые установки меняют форму.

Не только это, но я помню, что видел пусковую установку или две, что позволяет не иметь никакой формы.

К сожалению, я не могу найти никакой информации об этой части, возможно, потому что это относительно новая функция. Для StackOverflow нет даже ключевого слова здесь.

Что я пробовал

Я пробовал читать о адаптивных значках, но не мог найти ссылку на сторону приемника.

Я знаю, что в нем есть 2 чертежа:

Я знаю, по крайней мере, как получить экземпляр AdaptiveIconDrawable из стороннего приложения (при условии, что он есть):

PackageManager pm = context.getPackageManager();
Intent launchIntentForPackage = pm.getLaunchIntentForPackage(packageName);
String fullPathToActivity = launchIntentForPackage.getComponent().getClassName();
ActivityInfo activityInfo = pm.getActivityInfo(new ComponentName(packageName, fullPathToActivity), 0);
int iconRes = activityInfo.icon;
Drawable drawable = pm.getDrawable(packageName, iconRes, activityInfo.applicationInfo); // will be AdaptiveIconDrawable, if the app has it

Вопросы

  • Учитывая экземпляр AdaptiveIconDrawable, как вы его формируете, чтобы быть круглой формы, прямоугольника, закругленного прямоугольника, слезы и т.д.?

  • Как удалить фигуру и по-прежнему иметь допустимый размер значка (используя его передний план в нем)? Официальный размер значка приложения для пусковых установок - 48 дп, в то время как официальные для внутренних чертежей AdaptiveIconDrawable - 72dp (передний план), 108dp (фон). Я предполагаю, что это означало бы, что выкладывать передний план, изменить его каким-то образом и преобразовать в растровое изображение.

  • В каком случае полезно использовать IconCompat.createWithAdaptiveBitmap()? Было написано, что "Если вы создаете динамический ярлык с использованием растрового изображения, вы можете найти значок Support Library 26.0.0-beta2s IconCompat.createWithAdaptiveBitmap(), который полезен для обеспечения правильной маскировки вашего растрового изображения в соответствии с другими адаптивными значками"., но я не понимаю, в каких случаях это полезно.


EDIT: для создания растрового изображения из области переднего плана адаптивного значка, при изменении размера до нужного размера, я думаю, что это может быть хорошим решением:

val foregroundBitmap = convertDrawableToBitmap(drawable.foreground)
val targetSize = convertDpToPixels(this, ...).toInt()
val scaledBitmap = ThumbnailUtils.extractThumbnail(foregroundBitmap, targetSize, targetSize, ThumbnailUtils.OPTIONS_RECYCLE_INPUT)

fun convertDrawableToBitmap(drawable: Drawable?): Bitmap? {
    if (drawable == null)
        return null
    if (drawable is BitmapDrawable) {
        return drawable.bitmap
    }
    val bounds = drawable.bounds
    val width = if (!bounds.isEmpty) bounds.width() else drawable.intrinsicWidth
    val height = if (!bounds.isEmpty) bounds.height() else drawable.intrinsicHeight
    val bitmap = Bitmap.createBitmap(if (width <= 0) 1 else width, if (height <= 0) 1 else height,
            Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    drawable.setBounds(0, 0, canvas.width, canvas.height)
    drawable.draw(canvas)
    drawable.bounds = bounds;
    return bitmap
}

fun convertDpToPixels(context: Context, dp: Float): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics)

Возможно, вы сможете избежать двух растровых изображений одновременно, но это нормально, я думаю.

О создании формы, выбирая различные типы, я все еще не уверен, как это сделать. Единственное решение, которое я видел в ответах ниже, - использовать округленный прямоугольник или круг, но есть другие формы (например, слеза), которые могут прийти на ум.

4b9b3361

Ответ 1

Я не понимаю, как, учитывая экземпляр AdaptiveIconDrawable, пусковые установки меняют форму.

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

У меня нет собственного образца, но Ник Батчер сделал отличный примерный проект и серию сообщений в блогах: AdaptiveIconPlayground.


Учитывая экземпляр AdaptiveIconDrawable, как вы его формируете, чтобы быть круглой формы, прямоугольника, закругленного прямоугольника, слезы и т.д.?

Самый простой способ - растеризовать drawable и рисовать растровое изображение с помощью шейдера, как это сделано в Nick AdaptiveIconView:

private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private val background: Bitmap

// ...

background = Bitmap.createBitmap(layerSize, layerSize, Bitmap.Config.ARGB_8888)
backgroundPaint.shader = BitmapShader(background, CLAMP, CLAMP)

// < rasterize drawable onto `background` >

// draw desired shape(s)
canvas.drawRoundRect(0f, 0f, iconSize.toFloat(), iconSize.toFloat(),
                cornerRadius, cornerRadius, backgroundPaint)

Как удалить фигуру и по-прежнему иметь действительный размер значка (используя его выделение переднего плана)? Официальный размер значка приложения для пусковых установок - 48 дп, в то время как официальные для внутренних чертежей AdaptiveIconDrawable - 72dp (передний план), 108dp (фон). Я предполагаю, что это означало бы, что бы вырезать передний план, изменить его каким-то образом и преобразовать в растровое изображение.

Если вам не нужен фон, просто не рисуйте его. Вы полностью контролируете ситуацию. Размер не имеет большого значения, потому что вы обычно знаете, насколько велики ваши значки. В документации указано, что на переднем плане и в фоновом режиме должно быть 108dp, поэтому вы можете просто уменьшить масштаб вашего чертежа. Если на переднем плане/фоне используется векторная графика, тогда размер действительно не имеет значения, так как вы можете просто нарисовать их, как бы вам ни хотелось.

Если вы растрируете передний план, вы можете сделать собственный чертеж, как показано выше, или выбрать Canvas#drawBitmap(...), который также предлагает несколько вариантов рисования растрового изображения, в том числе передать в матрицу преобразования или просто некоторые границы.

Если вы не растеризуете свою выносливость, вы также можете использовать drawable.setBounds(x1, y1, x2, y2), где вы можете установить границы, на которые должен рисовать drawable. Это также должно работать.

В каком случае полезно использовать IconCompat.createWithAdaptiveBitmap()? Было написано, что "Если вы создаете динамический ярлык с использованием растрового изображения, вы можете найти значок Support Library 26.0.0-beta2s IconCompat.createWithAdaptiveBitmap(), который полезен для обеспечения правильной маскировки вашего растрового изображения в соответствии с другими адаптивными значками"., но я не понимаю, в каких случаях это полезно.

ShortCutInfo.Builder имеет метод setIcon(Icon icon), где вам нужно передать его. (И то же самое относится к версиям совместимости)

Кажется, что Icon используется для управления видом растрового изображения, которое передается как значок. Прямо сейчас я не мог найти другого использования для значка. Я не думаю, что вы использовали бы это при создании пусковой установки.


Дополнительная информация, отражающая последний комментарий

Вы завершаете класс AdaptiveIconDrawable с помощью своего собственного ресурса? Я просто хочу преобразовать его как-то в то, что я могу использовать, как для ImageView, так и для Bitmap, и я хочу контролировать форму, используя все фигуры, которые я показал на скриншоте выше. Как мне это сделать?

Если вы следуете приведенным выше ссылкам, вы можете увидеть пользовательский AdaptiveIconView, который рисует AdaptiveIconDrawable, поэтому индивидуальный вид определенно является опцией, но все упомянутое может быть перемещено так же легко в пользовательский Drawable, который вы тогда могли бы также используйте базовый ImageView.

Вы можете использовать различные фоны, используя методы, доступные на Canvas, вместе с BitmapShader, как показано выше, например. кроме drawRoundRect, мы имели бы

canvas.drawCircle(centerX, centerY, radius, backgroundPaint) // circle
canvas.drawRect(0f, 0f, width, height, backgroundPaint) // rect
canvas.drawPath(path, backgroundPaint) // more complex shapes

Чтобы переключиться между фоновыми фигурами, вы можете использовать что-либо из if/else, над композицией, наследованием и просто нарисовать нужную вам форму.

Ответ 2

Пусковые установки имеют гораздо меньше ограничений, чем приложения, поэтому они могут использовать другие подходы, но одно решение было хорошо продемонстрировано в Nick Butcher Adaptive Icon Playground.

Класс, который вам интересен, это Adaptive Icon View, который отображает адаптированные версии значка, создавая растр каждого слоя с фоном как растровое изображение холста, а затем рисование этих слоев в виде закругленных прямоугольников для реализации обрезки.

Связанное репо будет более информативным и включает примеры того, как преобразовать слой для эффектов перемещения и т.д., но вот базовый псевдокод для "адаптации значка" в представлении изображения:

setIcon() {
    //erase canvas first...
    canvas.setBitmap(background)
    drawable.setBounds(0, 0, layerSize, layerSize)
    drawable.draw(canvas)
}

onDraw() {
    //draw shadow first if needed...
    canvas.drawRoundRect(..., cornerRadius, backgroundPaint)
    canvas.drawRoundRect(..., cornerRadius, foregroundPaint)
}

Ответ 3

Так как Launcher - это просто Activity, вы можете рисовать что угодно. Вы можете рисовать иконки приложений, такие как пони, которые работают на красивых анимированных облаках. Это ваш мир, который подчиняется только вашим правилам.

Далее... В мире программирования нет волшебства. Если вы сталкиваетесь с магией, просто используйте декомпиляторы (с Java это очень просто), найдите код, ответственный за магию, запишите его и напишите замечательное сообщение в блоге о том, как эта магия работает.

Учитывая экземпляр AdaptiveIconDrawable, как вы его формируете, чтобы быть круглой формы, прямоугольника, закругленного прямоугольника, слезы и т.д.

Вы можете использовать AdaptiveIconDrawable.getBackground() и добавить к нему любую маску. Фактически, вы можете делать все, что хотите, с помощью значка, AdaptiveIconDrawable - это просто путь, где вы можете легко и просто разделить передний план и фон, без сложных фильтров или нейронных сетей. Добавьте параллакс, анимацию и еще много эффектов, теперь у вас есть 2 слоя для него.