Значок значка панели инструментов на Android
Я заметил, что использование тем AppCompat, иконки панели инструментов по умолчанию становятся тонированными атрибутом colorControlNormal
в моем стиле.
<style name="MyTheme" parent="Theme.AppCompat">
<item name="colorControlNormal">@color/yellow</item>
</style>
![enter image description here]()
Как вы можете видеть выше, однако, это не происходит со всеми значками. Я предоставил знак "плюс", который я получил из официальных значков, и он не становится тонированным (я использовал "белую" версию png). Из того, что я понял из этого question, система отображает только значки только с альфа-каналом. Это правда?
Если это так: Есть ли место, где я могу найти знаковые значки, определенные в форме? Если нет - и если значки на панели инструментов должны быть альфа-только для тонирования - как Google ожидает, что мы будем использовать предоставленные значки на панели инструментов?
Где-то в SDK я нашел несколько значков, заканчивающихся на _alpha.png
, и они действительно хорошо окрашиваются. Однако мне нужен полный набор значков материалов, и из официальных источников я мог найти только теги white
, grey600
и black
.
Применение ColorFilter
во время выполнения было бы немного болезненным, и моя фактическая панель инструментов - с некоторыми значками, тонированными, а некоторые другие - выглядят неплохо.
Ответы
Ответ 1
Я вижу, что этот вопрос дает некоторые взгляды, поэтому я собираюсь опубликовать ответ для тех, кто не читает комментарии.
Мои гипотезы в вопросе были неправы, и это не вопрос альфа-каналов, по крайней мере, не извне. Дело в том, что, цитируя @alanv,
AppCompat только оттенки собственных значков. Пока вам нужно будет вручную оттенок любых значков, которые вы предоставляете отдельно от AppCompat.
Это может измениться в будущем, но также может и не быть. Из этого ответа вы также можете увидеть список значков (все они принадлежат к внутренней папке ресурсов appcompat, поэтому вы не можете их изменить), которые автоматически тонируются и с которым цвет.
Лично я использую colorControlNormal
, который является черным или белым (или похожим оттенком), и импортирует значки с этим конкретным цветом. Цветные значки на цветном фоне выглядят немного плохо. Однако другое решение, которое мне показалось приятным, этот класс на github. Вы просто вызываете MenuColorizer.colorMenu()
при создании меню.
Ответ 2
Другой вариант - использовать новую поддержку векторных чертежей в библиотеке поддержки.
См. 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>
Ответ 3
Вот решение, которое я использую. Вызовите tintAllIcons после onPrepareOptionsMenu или эквивалентного местоположения. Причиной 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>
Это работает с appcompat v23.1.0.
Ответ 4
Я действительно смог сделать это на API 10 (Gingerbread), и он работал очень хорошо.
Изменить: он также работал с 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);
}
На этом этапе вы можете изменить его на любой желаемый цвет!
Ответ 5
Это окончательный и верный ответ. Сначала создайте стиль для панели инструментов следующим образом:
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" >
<item name="iconTint">@color/primaryTextColor</item>
<!--choice your favorite color-->
</style>
Затем в своем основном приложении или теме деятельности добавьте эту строку
<item name="actionBarPopupTheme">@style/AppTheme.PopupOverlay</item>
И, наконец, в вашем файле макета добавьте эту строку на панель инструментов
android:theme="?attr/actionBarPopupTheme"
И тогда вы увидите значки панели инструментов, окрашенные в ваш любимый цвет
Ответ 6
Вы можете создать собственную панель инструментов, которая использует цвет оттенка при раздувании меню.
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)
);
}
}
Просто убедитесь, что вы вызываете свой код Activity/Fragment:
toolbar.inflateMenu(R.menu.some_menu);
toolbar.setOnMenuItemClickListener(someListener);
Нет отражения, нет просмотра вида, и не столько кода, а?
И не используйте onCreateOptionsMenu/onOptionsItemSelected
, если вы используете этот подход
Ответ 7
Для SDK 23 или выше:
<style name="AppThemeToolbar" parent="MyAppTheme">
....
<item name="android:drawableTint">@color/secondaryLightColor</item>
</style>
Моя панель инструментов
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:theme="@style/AppThemeToolbar"
android:layout_width="match_parent"
android:layout_height="attr/actionBarSize">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
Ответ 8
@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);
![введите описание изображения здесь]()
Ответ 9
С androidX вы можете определить свою панель инструментов, как это
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/Toolbar" />
Затем расширьте тему AppCompat и установите свойство colorControlNormal так, как вам нравится:
<style name="Toolbar" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">@color/colorBaseWhite</item>
<item name="android:background">@color/colorPrimary</item>
</style>
Ответ 10
Это можно сделать в Котлине с помощью:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
menu.getItem(0)?.icon?.setTint(Color.WHITE)
}
else {
@Suppress("DEPRECATION")
menu.getItem(0)?.icon?.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
}
Он должен работать на всех современных версиях Android и без сбоев завершится, если getItem
или icon
вернет ноль.
Ответ 11
В основном, когда вы устанавливаете меню, значок из трех точек приобретает цвет android: textColorSecondary из AppTheme, который по умолчанию имеет значение Black.
Поэтому, если вы не используете textColorSecondary в любом месте вашего проекта, вы можете просто добавить следующую строку
<item name="android:textColorSecondary">@color/White</item>
После добавления это может выглядеть так.
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorSecondary">@color/White</item>
</style>