23

Я заметил, что, используя темы AppCompat, значки панели инструментов по умолчанию становятся тонированными атрибутом colorControlNormal в моем стиле.Значок значка панели инструментов на Android

<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

AppCompat только Оттенки свои собственные иконки. На данный момент вам нужно будет вручную направить любые значки, которые вы предоставляете отдельно от AppCompat. – alanv

+0

Кроме того, связанный вопрос касается только уведомлений, а не общего оттенка. – alanv

+1

См. Также [этот StackO-Post] (http://stackoverflow.com/questions/26780046/menuitem-tinting-on-appcompat-toolbar) для подробного объяснения. – reVerse

ответ

4

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

Мои гипотезы в вопросе были неправы, и это не вопрос альфа-каналов, по крайней мере, не извне. Дело в том, что, цитируя @alanv,

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

Это может измениться в будущем, но также может и не быть. С this answer вы также можете увидеть список значков (все они принадлежат папке внутренних ресурсов appcompat, поэтому вы не можете их изменить), которые автоматически тонируются и с каким цветом.

Лично я использую colorControlNormal, который является черным или белым (или подобным оттенком), и импортирует значки с определенным цветом. Цветные значки на цветном фоне выглядят немного плохо. Однако другое решение, которое я нашел приятным, - this class на github. Вы просто вызываете MenuColorizer.colorMenu() при создании меню.

+0

Я думаю, вы должны взглянуть на мой ответ выше ... –

19

Вот решение, которое я использую. Вызовите 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); 
       } 
      } 
     } 
    } 
} 

Это не будет заботиться о переполнении, но для этого, вы можете сделать это:

Layout:

<android.support.v7.widget.Toolbar 
    ... 
    android:theme="@style/myToolbarTheme" /> 

Стили:

<style name="myToolbarTheme"> 
     <item name="colorControlNormal">#FF0000</item> 
</style> 

это работает с appcompat v23.1.0.

4

Вы можете создать собственную панель инструментов, которая использует цвет оттенка при раздувании меню.

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, если вы используете этот подход

18

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

См res/xml/ic_search.xml в блоге AppCompat — Age of the vectors

Обратите внимание, ссылка на ?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> 
+0

В чем разница между использованием '? Attr/colorControlNormal' в атрибутах' android: tint' и 'android: fillColor'? Благодаря! –

+0

@SuperThomasLab Пример из блога Chris Banes, где он иллюстрирует замену тонированного изображения тонированным вектором. Обратите внимание, что fillColor был эффективно жестко закодирован в исходном изображении. Я не знаю, поддерживаются ли в AppCompat другие цветовые представления. –

11

Я на самом деле был в состоянии сделать это на API 10 (Gingerbread), и она работала очень хорошо.

Edit: Он работал на API 22 также ...

Вот конечный результат.

enter image description here

Примечание: Значок представляет собой вытяжку ресурса в вытяжке папки (ы).

Теперь вот как его сделать:

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

На данный момент вы можете изменить его в любой цвет вы хотите!

0
@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); 

enter image description here

Смежные вопросы