web-dev-qa-db-fra.com

Icône de la barre d'outils teintée sur Android

J'ai remarqué qu'en utilisant les thèmes AppCompat, les icônes de la barre d'outils par défaut sont teintées par l'attribut colorControlNormal dans mon style.

<style name="MyTheme" parent="Theme.AppCompat">
    <item name="colorControlNormal">@color/yellow</item>
</style>

enter image description here

Comme vous pouvez le voir ci-dessus, cependant, cela ne se produit pas avec toutes les icônes. J'ai fourni le signe "plus", que j'ai reçu des icônes officielles, et il n'est pas teinté (j'ai utilisé la version "blanche" du png). D'après ce que j'ai compris de cette question , le système ne colore que les icônes avec un canal alpha. Est-ce vrai?

Si oui: Y a-t-il un endroit où je peux trouver des icônes matérielles officielles définies par alpha? Si ce n'est pas le cas - et si les icônes de la barre d'outils doivent uniquement être alpha pour être teintées - comment Google s'attend-il à ce que nous utilisions les icônes fournies dans une barre d'outils?

Quelque part dans le Kit de développement logiciel (SDK), j'ai trouvé des icônes se terminant par _alpha.png, qui sont en fait bien teintées. Cependant, il me faut l’ensemble complet des icônes matérielles et, de la part des sources officielles, je ne pouvais en trouver que white, grey600 et black

L'application d'une ColorFilter au moment de l'exécution serait légèrement pénible, et ma barre d'outils actuelle - avec certaines icônes teintées, d'autres pas - semble assez mauvaise.

29
natario

Je vois que la question suscite des points de vue et je vais donc poster une réponse pour ceux qui ne lisent pas les commentaires.

Mes conjectures dans la question étaient toutes fausses et il ne s'agissait pas de canaux alpha, du moins pas de l'extérieur. Le fait est simplement que, citant @alanv,

AppCompat teinte uniquement ses propres icônes. Pour le moment, vous devrez manuellement Teintez les icônes que vous fournissez séparément d'AppCompat.

Cela pourrait changer dans le futur mais pourrait ne pas en être autrement. De cette réponse vous pouvez également voir la liste des icônes (elles appartiennent toutes au dossier de ressources interne d’appcompat, vous ne pouvez donc pas les changer) qui sont automatiquement teintées et avec quelle couleur.

Personnellement, j'utilise une variable colorControlNormal qui est noire ou blanche (ou des nuances similaires) et importe les icônes avec cette couleur particulière. Les icônes colorées sur un fond coloré ont l’air un peu mauvais. Cependant, une autre solution que j'ai trouvée agréable est cette classe sur github. Vous appelez simplement MenuColorizer.colorMenu() lorsque vous créez le menu.

6
natario

Une autre option consiste à utiliser le nouveau support pour les dessins vectoriels dans la bibliothèque de support.

Voir res/xml/ic_search.xml dans l'article de blog AppCompat - L'âge des vecteurs

Notez la référence à ?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>
22
Joe Bowbeer

Voici la solution que j'utilise. Appelez tintAllIcons après le onPrepareOptionsMenu ou l’emplacement équivalent. La raison de mutate () est si vous utilisez les icônes à plusieurs endroits. sans la mutation, ils prendront tous la même teinte.

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

Cela ne résoudra pas le problème de débordement, mais pour cela, vous pouvez le faire:

Disposition:

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

Modes:

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

Cela fonctionne à partir de appcompat v23.1.0.

20
Learn OpenGL ES

En fait, je pouvais le faire sur API 10 (Gingerbread) et cela fonctionnait très bien.

Edit: Cela fonctionnait aussi avec l'API 22 ...

Voici le résultat final.

 enter image description here

Remarque: L'icône est une ressource pouvant être dessinée dans le ou les dossiers pouvant être dessinés.

Maintenant, voici comment ça se fait:

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

À ce stade, vous pouvez le changer en n'importe quelle couleur!

15
Yusuph wickama

Vous pouvez simplement créer une barre d’outils personnalisée qui utilise votre couleur pour gonfler le menu.

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

}

Assurez-vous simplement que vous appelez votre code d'activité/fragment:

toolbar.inflateMenu(R.menu.some_menu);
toolbar.setOnMenuItemClickListener(someListener);

Pas de réflexion, pas de recherche de vue, et pas tellement de code, hein?

Et n'utilisez pas onCreateOptionsMenu/onOptionsItemSelected, si vous utilisez cette approche

4
Drew

Pour SDK 23 ou supérieur:

<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>

3
mlunap

C'est la réponse finale et vraie Créez d’abord un style pour la barre d’outils comme ceci:

  <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" >
     <item name="iconTint">@color/primaryTextColor</item>
    <!--choice your favorite color-->
  </style>

Puis, dans votre application principale ou votre thème d'activité, ajoutez cette ligne

  <item name="actionBarPopupTheme">@style/AppTheme.PopupOverlay</item>

Et enfin, dans votre fichier de mise en page, ajoutez cette ligne à votre barre d’outils

 Android:theme="?attr/actionBarPopupTheme"

Et ensuite, vous verrez les icônes de votre barre d’outils colorées dans votre couleur préférée.

3
Ali mohammadi
@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;
 }

et appelez de cette manière:

MenuItem location = menu.findItem(R.id.action_location);
DrawableUtils.setTintDrawable(location.getIcon(), Color.WHITE);

 enter image description here

0
chry