Android: Tint usando DrawableCompat

Sto tentando di colorare un’immagine prima del livello API di Android 21. Ho colorato con successo gli elementi utilizzando:

 

Tuttavia, non riesco a capire come farlo attraverso il codice su un ImageView:

 Drawable iconDrawable = this.mContext.getResources().getDrawable(R.drawable.somedrawable); DrawableCompat.setTint(iconDrawable, this.mContext.getResources().getColor(R.color.red)); imageView.setImageDrawable(iconDrawable); 

Ho provato a impostare il TintMode, ma questo non sembra essere diverso. Sto usando la class di compatibilità v4 DrawableCompat in modo errato?

Il modo più semplice per colorare multipiattaforma (se non hai bisogno di ColorStateList) è:

 drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); 

Non dimenticare di mutare il Drawable prima di applicare il filtro.

Nel caso in cui qualcuno debba usare la colorazione di DrawableCompat senza influenzare altri drawable, ecco come lo si fa con mutate() :

 Drawable drawable = getResources().getDrawable(R.drawable.some_drawable); Drawable wrappedDrawable = DrawableCompat.wrap(drawable); wrappedDrawable = wrappedDrawable.mutate(); DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.white)); 

Che può essere semplificato per:

 Drawable drawable = getResources().getDrawable(R.drawable.some_drawable); drawable = DrawableCompat.wrap(drawable); DrawableCompat.setTint(drawable.mutate(), getResources().getColor(R.color.white)); 

La tinta precedente non era supportata da DrawableCompat . A partire dalla libreria di supporto 22.1 è ansible farlo, ma è necessario farlo in questo modo:

 Drawable normalDrawable = getResources().getDrawable(R.drawable.drawable_to_tint); Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable); DrawableCompat.setTint(wrapDrawable, getResources().getColor(R.color.colorPrimaryLight)); 

Le risposte qui non funzionano per i dispositivi pre-lollipop (SupportLib 23.4.0), ma ho pubblicato una soluzione alternativa che funziona per API 17 e versioni successive: https://stackoverflow.com/a/37434219/2170109

Il seguente codice è stato testato e funziona sulle API 17, 19, 21, 22, 23 e N Anteprima 3:

  // https://stackoverflow.com/a/30928051/2170109 Drawable drawable = DrawableCompat.wrap(ContextCompat.getDrawable(context, R.drawable.vector)); image.setImageDrawable(drawable); /* * need to use the filter | https://stackoverflow.com/a/30880522/2170109 * (even if compat should use it for pre-API21-devices | https://stackoverflow.com/a/27812472/2170109) */ int color = ContextCompat.getColor(context, R.color.yourcolor); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { DrawableCompat.setTint(drawable, color); } else { drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); } 

Se guardi il codice sorgente di DrawableCompat, vedrai che per qualsiasi versione <21 il metodo non fa nulla .

L’idea di DrawableCompat sembra semplicemente non andare in crash su vecchie versioni, piuttosto che fornire effettivamente quella funzionalità.

Con la libreria di supporto 22.1 è ansible utilizzare DrawableCompat per disegnare tinta.

DrawableCompat.wrap (Drawable) e setTint (), setTintList () e setTintMode () funzioneranno: non c’è bisogno di creare e mantenere drawable separati solo per supportare più colors!

Condividerò la mia soluzione qui perché potrebbe far risparmiare tempo a qualcuno.

Avevo un ImageView con drawable vettoriale usato come sorgente drawable (in realtà, era Support Vector Drawable dalla libreria di supporto Android 23.3). Quindi, prima l’ho avvolto in questo modo:

mImageView.setImageDrawable(DrawableCompat.wrap(mImageView.getDrawable()));

E dopo ho provato ad applicare la tinta in questo modo:

 DrawableCompat.setTint( mImageView.getDrawable(), getResources().getColor(R.color.main_color) ); 

Senza fortuna.

Ho provato a chiamare mutate() su drawable avvolto, così come su drawable originale – ancora senza fortuna. invalidate() chiamato su mImageView fatto il trucco.