AppCompatテーマを使用すると、デフォルトのツールバーアイコンが私のスタイルのcolorControlNormal
属性によって色付けされることに気付きました。
<style name="MyTheme" parent="Theme.AppCompat">
<item name="colorControlNormal">@color/yellow</item>
</style>
ただし、上記のように、すべてのアイコンで発生するわけではありません。 「プラス」記号を提供しました。これは公式アイコンから取得したもので、色付けされていません(「白色」バージョンのpngを使用しました)。私がこれから理解したことから 質問 、システムはアルファチャンネルだけのアイコンのみを色付けします。これは本当ですか?
その場合:アルファ定義された公式の素材アイコンを見つけることができる場所はありますか?そうでない場合-ツールバーアイコンをアルファのみで着色する必要がある場合-Googleはツールバーで提供されたアイコンを使用することをどのように期待していますか?
SDKのどこかで_alpha.png
で終わるアイコンを見つけましたが、実際にはうまく色付けされています。ただし、マテリアルアイコンの完全なセットが必要であり、公式ソースからは、white
、grey600
、およびblack
のアイコンのみが見つかりました。
実行時にColorFilter
を適用するのは少し苦痛であり、私の実際のツールバー-いくつかのアイコンが着色されていて、他のアイコンは着色されていない-は非常に悪く見えます。
この質問にはいくつかの意見がありますので、コメントを読んでいない人には答えを投稿します。
質問の私の推測はすべて間違っていて、それはアルファチャンネルの問題ではなく、少なくとも外部的には問題ではありません。事実は、@alanvを引用して、
AppCompatは、独自のアイコンにのみ色を付けます。今のところ、AppCompatとは別に提供するアイコンを手動で色付けする必要があります。
これは将来変更される可能性がありますが、変更されない場合もあります。 この回答 から、自動的に色付けされ、どの色のアイコンのリスト(すべてappcompatの内部リソースフォルダーに属しているため、変更できません)を見ることができます。
個人的には、黒または白(または同様の色合い)のcolorControlNormal
を使用し、その特定の色のアイコンをインポートします。色付きの背景にある色付きのアイコンは少し悪く見えます。しかし、私が快適だと感じた別の解決策は、githubの このクラス メニューを作成するときにMenuColorizer.colorMenu()
を呼び出すだけです。
もう1つのオプションは、サポートライブラリのベクトルドロウアブルの新しいサポートを使用することです。
ブログ投稿のres/xml/ic_search.xml
を参照してください AppCompat — Age of the vector
?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>
ここに私が使用するソリューションがあります。 onPrepareOptionsMenuまたは同等の場所の後にtintAllIconsを呼び出します。 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以降で機能します。
実際、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);
}
この時点で、任意の色に変更できます!
これが最終的な真実の答えです最初に、次のようなツールバーのスタイルを作成します。
<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"
そして、あなたはあなたの好きな色で色付けされたツールバーアイコンを見るでしょう
メニューを拡大するときに色合いの色を使用するカスタムツールバーを作成できます。
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
を使用しないでください
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>
@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);
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>