Тонировка значков панели инструментов на Android
Я заметил, что при использовании тем AppCompat значки панели инструментов по умолчанию окрашиваются атрибутом colorControlNormal в моем стиле.
<style name="MyTheme" parent="Theme.AppCompat">
<item name="colorControlNormal">@color/yellow</item>
</style>

Если да : есть ли место, где я могу найти Альфа-определенные, официальные материальные значки? Если нет - и если значки панели инструментов должны быть только альфа-тонированными - как Google ожидает, что мы будем использовать предоставленные значки в панели инструментов?
Где-то в SDK я нашел несколько иконок, заканчивающихся на _alpha.png, и они действительно хорошо тонируются. Однако мне нужен полный набор материальных иконок, а из официальных источников я смог найти только white, grey600 и black единицы.
Применение a ColorFilter при время выполнения будет немного болезненным, и моя фактическая панель инструментов - с некоторыми тонированными значками, некоторые другие нет - выглядит довольно плохо.
6 ответов:
Здесь решение, которое я использую. Вызовите tintAllIcons после onPrepareOptionsMenu или эквивалентного местоположения. Причина mutate() заключается в том, что вы используете значки в нескольких местах; без mutate все они будут иметь одинаковый оттенок.
public class MenuTintUtils { public static void tintAllIcons(Menu menu, final int color) { for (int i = 0; i < menu.size(); ++i) { final MenuItem item = menu.getItem(i); tintMenuItemIcon(color, item); tintShareIconIfPresent(color, item); } } private static void tintMenuItemIcon(int color, MenuItem item) { final Drawable drawable = item.getIcon(); if (drawable != null) { final Drawable wrapped = DrawableCompat.wrap(drawable); drawable.mutate(); DrawableCompat.setTint(wrapped, color); item.setIcon(drawable); } } private static void tintShareIconIfPresent(int color, MenuItem item) { if (item.getActionView() != null) { final View actionView = item.getActionView(); final View expandActivitiesButton = actionView.findViewById(R.id.expand_activities_button); if (expandActivitiesButton != null) { final ImageView image = (ImageView) expandActivitiesButton.findViewById(R.id.image); if (image != null) { final Drawable drawable = image.getDrawable(); final Drawable wrapped = DrawableCompat.wrap(drawable); drawable.mutate(); DrawableCompat.setTint(wrapped, color); image.setImageDrawable(drawable); } } } } }Это не будет заботиться о переполнении, но для этого вы можете сделать следующее:
Расположение:
<android.support.v7.widget.Toolbar ... android:theme="@style/myToolbarTheme" />Стили:
<style name="myToolbarTheme"> <item name="colorControlNormal">#FF0000</item> </style>Это работает в совместимости приложений v23.1.0.
Другой вариант-использовать новую поддержку векторных чертежей в библиотеке поддержки.
Смотрите
res/xml/ic_search.xmlв блоге AppCompat-возраст векторовОбратите внимание на ссылку на
?attr/colorControlNormal<vector xmlns:android="..." android:width="24dp" android:height="24dp" android:viewportWidth="24.0" android:viewportHeight="24.0" android:tint="?attr/colorControlNormal"> <path android:pathData="..." android:fillColor="@android:color/white"/> </vector>
Я действительно смог сделать это на API 10 (Gingerbread), и это сработало очень хорошо.
Edit : Он также работал на API 22...
Вот окончательный результат.
Примечание: значок-это ресурс с возможностью рисования в папке (папках) с возможностью рисования.
Теперь вот как это делается:
@Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); MenuItem item = menu.findItem(R.id.action_refresh); Drawable icon = getResources().getDrawable(R.drawable.ic_refresh_white_24dp); icon.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_IN); item.setIcon(icon); }В этот момент Вы можете изменить его на любой цвет, который вы хотите!
Я вижу, что этот вопрос получает некоторые мнения, поэтому я собираюсь опубликовать ответ для тех, кто не читает комментарии.
Все мои предположения в этом вопросе были ошибочными, и дело не в Альфа-каналах, по крайней мере, не во внешнем мире. Дело просто в том, что, цитируя @alanv,AppCompat только подкрашивает свои собственные иконки. На данный момент вам нужно будет вручную подкрашивайте любые значки, которые вы предоставляете отдельно от AppCompat.
Это может измениться в будущем, но также а может, и нет. Из этого ответа вы также можете увидеть список значков (все они принадлежат внутренней папке ресурсов appcompat, поэтому вы не можете их изменить), которые автоматически подкрашиваются и каким цветом.
Лично я использую
colorControlNormal, который является черным или белым (или подобными оттенками), и импортирую значки с этим конкретным цветом. Цветные значки на цветном фоне выглядят немного плохо. Однако другое решение, которое я нашел приятным, - это этот класс на github. Ты просто позвониMenuColorizer.colorMenu()при создании меню.
Вы можете просто создать пользовательскую панель инструментов, которая использует ваш оттенок цвета при раздувании меню.
public class MyToolbar extends Toolbar { ... some constructors, extracting mAccentColor from AttrSet, etc @Override public void inflateMenu(@MenuRes int resId) { super.inflateMenu(resId); Menu menu = getMenu(); for (int i = 0; i < menu.size(); i++) { MenuItem item = menu.getItem(i); Drawable icon = item.getIcon(); if (icon != null) { item.setIcon(applyTint(icon)); } } } void applyTint(Drawable icon){ icon.setColorFilter( new PorterDuffColorFilter(mAccentColor, PorterDuff.Mode.SRC_IN) ); } }Просто убедитесь, что вы вызываете код действия / фрагмента:
toolbar.inflateMenu(R.menu.some_menu); toolbar.setOnMenuItemClickListener(someListener);Никакого отражения, никакого просмотра и не так много кода, да?
И не используйте
onCreateOptionsMenu/onOptionsItemSelected, Если вы используете этот подход
@NonNull public static Drawable setTintDrawable(@NonNull Drawable drawable, @ColorInt int color) { drawable.clearColorFilter(); drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); drawable.invalidateSelf(); Drawable wrapDrawable = DrawableCompat.wrap(drawable).mutate(); DrawableCompat.setTint(wrapDrawable, color); return wrapDrawable; }И вызовите таким образом:
MenuItem location = menu.findItem(R.id.action_location); DrawableUtils.setTintDrawable(location.getIcon(), Color.WHITE);

