Przyciemnianie menu na pasku narzędzi AppCompat
Kiedy używam drawables z biblioteki AppCompat
dla moich pozycji menu Toolbar
, przyciemnianie działa zgodnie z oczekiwaniami. Tak:
<item
android:id="@+id/action_clear"
android:icon="@drawable/abc_ic_clear_mtrl_alpha" <-- from AppCompat
android:title="@string/clear" />
Ale jeśli użyję własnych rysunków lub nawet skopiuję je z biblioteki AppCompat
do własnego projektu, to w ogóle nie będzie to odcień.
<item
android:id="@+id/action_clear"
android:icon="@drawable/abc_ic_clear_mtrl_alpha_copy" <-- copy from AppCompat
android:title="@string/clear" />
Czy jest jakaś specjalna magia w AppCompat
Toolbar
to tylko odcień rysunków z tej biblioteki? Jakiś sposób, żeby to zadziałało z moimi własnymi rysunkami?
Uruchamianie tego na urządzeniu poziomu API 19 z compileSdkVersion = 21
i targetSdkVersion = 21
, a także używając wszystkiego z AppCompat
abc_ic_clear_mtrl_alpha_copy
jest dokładną kopią abc_ic_clear_mtrl_alpha
png z AppCompat
Edit:
Przyciemnianie jest oparte na wartości, którą ustawiłem dla android:textColorPrimary
w moim temacie.
Np. <item name="android:textColorPrimary">#00FF00</item>
dałby mi zielony odcień.
Zrzuty ekranu
Przyciemnianie działa zgodnie z oczekiwaniami przy użyciu drawable from AppCompat
Przyciemnianie nie działa z drawable copied from AppCompat
6 answers
Ponieważ jeśli spojrzysz na kod źródłowy Menedżera TintManager w AppCompat, zobaczysz:
/**
* Drawables which should be tinted with the value of {@code R.attr.colorControlNormal},
* using the default mode.
*/
private static final int[] TINT_COLOR_CONTROL_NORMAL = {
R.drawable.abc_ic_ab_back_mtrl_am_alpha,
R.drawable.abc_ic_go_search_api_mtrl_alpha,
R.drawable.abc_ic_search_api_mtrl_alpha,
R.drawable.abc_ic_commit_search_api_mtrl_alpha,
R.drawable.abc_ic_clear_mtrl_alpha,
R.drawable.abc_ic_menu_share_mtrl_alpha,
R.drawable.abc_ic_menu_copy_mtrl_am_alpha,
R.drawable.abc_ic_menu_cut_mtrl_alpha,
R.drawable.abc_ic_menu_selectall_mtrl_alpha,
R.drawable.abc_ic_menu_paste_mtrl_am_alpha,
R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha,
R.drawable.abc_ic_voice_search_api_mtrl_alpha,
R.drawable.abc_textfield_search_default_mtrl_alpha,
R.drawable.abc_textfield_default_mtrl_alpha
};
/**
* Drawables which should be tinted with the value of {@code R.attr.colorControlActivated},
* using the default mode.
*/
private static final int[] TINT_COLOR_CONTROL_ACTIVATED = {
R.drawable.abc_textfield_activated_mtrl_alpha,
R.drawable.abc_textfield_search_activated_mtrl_alpha,
R.drawable.abc_cab_background_top_mtrl_alpha
};
/**
* Drawables which should be tinted with the value of {@code android.R.attr.colorBackground},
* using the {@link android.graphics.PorterDuff.Mode#MULTIPLY} mode.
*/
private static final int[] TINT_COLOR_BACKGROUND_MULTIPLY = {
R.drawable.abc_popup_background_mtrl_mult,
R.drawable.abc_cab_background_internal_bg,
R.drawable.abc_menu_hardkey_panel_mtrl_mult
};
/**
* Drawables which should be tinted using a state list containing values of
* {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated}
*/
private static final int[] TINT_COLOR_CONTROL_STATE_LIST = {
R.drawable.abc_edit_text_material,
R.drawable.abc_tab_indicator_material,
R.drawable.abc_textfield_search_material,
R.drawable.abc_spinner_mtrl_am_alpha,
R.drawable.abc_btn_check_material,
R.drawable.abc_btn_radio_material
};
/**
* Drawables which contain other drawables which should be tinted. The child drawable IDs
* should be defined in one of the arrays above.
*/
private static final int[] CONTAINERS_WITH_TINT_CHILDREN = {
R.drawable.abc_cab_background_top_material
};
Co w zasadzie oznacza, że mają konkretne zasoby do przyciemnienia.
Ale myślę, że zawsze można zobaczyć, jak przyciemniają te obrazy i zrobić to samo. To tak proste, jak ustawić filtr kolorów na rysunku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-08 14:05:38
Ustawienie a ColorFilter
(tint) na a MenuItem
jest proste. Oto przykład:
Drawable drawable = menuItem.getIcon();
if (drawable != null) {
// If we don't mutate the drawable, then all drawable's with this id will have a color
// filter applied to it.
drawable.mutate();
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
drawable.setAlpha(alpha);
}
Powyższy kod jest bardzo pomocny, jeśli chcesz obsługiwać różne motywy i nie chcesz mieć dodatkowych kopii tylko dla koloru lub przezroczystości.
Kliknij tutaj aby Klasa pomocnicza ustawiała ColorFilter
na wszystkich rysunkach w menu, łącznie z ikoną przepełnienia.
W onCreateOptionsMenu(Menu menu)
wystarczy zadzwonić MenuColorizer.colorMenu(this, menu, color);
po napompowaniu menu i voila; ikony są przyciemnione.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-19 09:21:34
Po nowej bibliotece wsparcia v22. 1, możesz użyć czegoś podobnego do tego:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
Drawable drawable = menu.findItem(R.id.action_clear).getIcon();
drawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(drawable, ContextCompat.getColor(this,R.color.textColorPrimary));
menu.findItem(R.id.action_clear).setIcon(drawable);
return true;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 06:13:25
Osobiście wolałem takie podejście od tego linku
Utwórz układ XML o następującej treści:
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_action_something"
android:tint="@color/color_action_icons_tint"/>
I odwołaj się do tego z menu:
<item
android:id="@+id/option_menu_item_something"
android:icon="@drawable/ic_action_something_tined"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-29 06:40:13
Większość rozwiązań w tym wątku albo używa nowszego API, albo używa reflection, albo używa intensywnego wyszukiwania widoku, aby dostać się do napompowanego MenuItem
.
Jest jednak bardziej eleganckie podejście do tego. Potrzebujesz niestandardowego paska narzędzi, ponieważ twój przypadek użycia "Zastosuj Niestandardowy odcień" nie gra dobrze z publicznym interfejsem API stylizacji/motywów.
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)
);
}
}
Po prostu upewnij się, że zadzwonisz do swojej aktywności/kodu fragmentu:
toolbar.inflateMenu(R.menu.some_menu);
toolbar.setOnMenuItemClickListener(someListener);
Brak refleksji, brak wyszukiwania widoku, i nie tyle Kod, co?
And now you można zignorować Śmieszne onCreateOptionsMenu/onOptionsItemSelected
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 14:12:28
Oto rozwiązanie, które używam; można wywołać go po onprepareoptionsmenu() lub równoważne miejsce. Powodem mutate () jest użycie ikon w więcej niż jednym miejscu; bez mutate wszystkie przybierają ten sam odcień.
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);
}
}
}
}
}
To nie zajmie się przepełnieniem, ale za to możesz to zrobić:
Układ:
<android.support.v7.widget.Toolbar
...
android:theme="@style/myToolbarTheme" />
Style:
<style name="myToolbarTheme">
<item name="colorControlNormal">#FF0000</item>
</style>
To działa od appcompat v23. 1. 0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-13 16:41:05