Cómo usar el selector para teñir imageview en android

Quiero teñir los íconos de mi tabhost usando xml, en lugar de hacerlo programáticamente (no pude hacer eso de todos modos) … Así que encontré este hilo en SO: Android imageview change tint para simular clic de botón

Esa parece ser una solución bastante buena, pero no pude adaptarla correctamente en mi proyecto … Hice los siguientes cambios:

public class TintableImageView extends ImageView { private ColorStateList tint; public TintableImageView(Context context) { super(context); } //this is the constructor that causes the exception public TintableImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public TintableImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } //here, obtainStyledAttributes was asking for an array private void init(Context context, AttributeSet attrs, int defStyle) { TypedArray a = context.obtainStyledAttributes(attrs, new int[]{R.styleable.TintableImageView_tint}, defStyle, 0); tint = a.getColorStateList(R.styleable.TintableImageView_tint); a.recycle(); } @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (tint != null && tint.isStateful()) updateTintColor(); } public void setColorFilter(ColorStateList tint) { this.tint = tint; super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); } private void updateTintColor() { int color = tint.getColorForState(getDrawableState(), 0); setColorFilter(color); } } 

Tampoco pude hacer referencia a @drawable/selector.xml en android:tint , así que lo hice en colors.xml:

   #2e7cb4 @drawable/tab_icon_selector  

Mi selector:

        

Mi diseño de pestaña:

      

¿Alguna sugerencia? Gracias por adelantado

[EDIT] NumberFormatException una NumberFormatException para usar android:tint NumberFormatException , cuando la app:tint era correcta app:tint (después de establecer xmlns:app="http://schemas.android.com/apk/res/com.myapp" ) .. .pero ahora creo que estoy usando mi selector de forma incorrecta, porque los icons son todos negros, sin importar el estado … He intentado configurar @drawable/tab_icon_selector desde dentro de colors.xml, no funcionó

[/EDITAR]

En referencia a mi solución en https://stackoverflow.com/a/18724834/2136792 , hay algunas cosas que te estás perdiendo:

TintableImageView.java

 @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (tint != null && tint.isStateful()) updateTintColor(); } public void setColorFilter(ColorStateList tint) { this.tint = tint; super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); } private void updateTintColor() { int color = tint.getColorForState(getDrawableState(), 0); setColorFilter(color); } 

drawableStateChanged () debe anularse para que el tinte se actualice cuando cambie el estado del elemento.

No estoy seguro de si hacer referencia a un dibujable de un dibujante puede causar un problema, pero simplemente puede mover su selector.xml a una carpeta “/ res / color” para hacer referencia a él con “@ color / selector.xml” (aapt fusiona ambos /res/values/colors.xml y la carpeta / res / color).

Si está en la API 21+, puede hacerlo fácilmente en XML con un selector y un tinte :

        

Implementé esto usando DrawableCompat de la biblioteca Android v4 de soporte.

Con un ImageButton regular (que subclasifica ImageView , por lo que esta información también se aplica a ImageView s), usando un icono negro de la colección de icons de materiales :

  

Este es el método de utilidad que creé:

 public static void tintButton(@NonNull ImageButton button) { ColorStateList colours = button.getResources() .getColorStateList(R.color.button_colour); Drawable d = DrawableCompat.wrap(button.getDrawable()); DrawableCompat.setTintList(d, colours); button.setImageDrawable(d); } 

Donde res/color/button_colour.xml es un selector que cambia el color del icono de rojo a rojo semitransparente cuando se presiona el botón:

      

Después de que se haya inflado onCreate() método onCreate() mi actividad, simplemente llamo al tintButton(...) helper una vez para cada botón.


He probado esto en Android 4.1 (mi minSdkVersion ) y en 5.0 dispositivos, pero DrawableCompat debería funcionar nuevamente para Android 1.6.

Con la biblioteca de soporte 22.1 podemos usar DrawableCompat para tinte drawable, nivel de API 4+

DrawableCompat.wrap (Drawable) y setTint (), setTintList (), y setTintMode () simplemente funcionarán: ¡no es necesario crear y mantener separables herramientas solo para admitir varios colores!

Estoy de acuerdo con @Dreaming in Code y daré un ejemplo.

ic_up_small

     

layout / item_post_count_info.xml

  

Atención: deberíamos usar la aplicación: tint en lugar de android: tint .

Mi versión de la biblioteca de soporte es 26.0.2.

app / build.gradle

 implementation 'com.android.support:appcompat-v7:26.0.2' implementation 'com.android.support:support-core-utils:26.0.2' implementation 'com.android.support:support-annotations:26.0.2' implementation 'com.android.support:support-v4:26.0.2' implementation 'com.android.support:design:26.0.2' 

Si usamos android: tint, se bloqueará y el registro será así:

E / AndroidRuntime: EXCEPCIÓN FATAL: principal android.view.InflateException: archivo XML binario línea # 0: error al inflar la clase en android.view.LayoutInflater.createView (LayoutInflater.java:613) en android.view.LayoutInflater.createViewFromTag (LayoutInflater. java: 687) en android.view.LayoutInflater.rInflate (LayoutInflater.java:746) en android.view.LayoutInflater.inflate (LayoutInflater.java:489) en android.view.LayoutInflater.inflate (LayoutInflater.java:396) en com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create (PostCountInfoViewHolder.java:29) en com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create (PostCountInfoViewHolder.java:25) en com.opera.six. collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.java:39) en com.opera.six.collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.java:19) en android.support.v7.widget.RecyclerView $ Adapter.createViewHolder (RecyclerView.java: 6493) en android.support.v7.widget.RecyclerView $ Recycler.tryGetViewHolderForPosit ionByDeadline (RecyclerView.java:5680) en android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java:5563) en android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java:5559) en android.support.v7.widget.LinearLayoutManager $ LayoutState.next (LinearLayoutManager.java:2229) en android.support.v7.widget.LinearLayoutManager.layoutChunk (LinearLayoutManager.java:1556) en android.support.v7.widget.LinearLayoutManager .fill (LinearLayoutManager.java:1516) en android.support.v7.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:608) en android.support.v7.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.java:3693) en android. support.v7.widget.RecyclerView.dispatchLayout (RecyclerView.java:3410) en android.support.v7.widget.RecyclerView.onLayout (RecyclerView.java:3962) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.support.v4.widget.SwipeRefreshLayout.onLayout (SwipeR efreshLayout.java:610) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.support.design.widget.HeaderScrollingViewBehavior.layoutChild (HeaderScrollingViewBehavior .java: 132) en android.support.design.widget.ViewOffsetBehavior.onLayoutChild (ViewOffsetBehavior.java:42) en android.support.design.widget.AppBarLayout $ ScrollingViewBehavior.onLayoutChild (AppBarLayout.java:1361) en android.support. design.widget.CoordinatorLayout.onLayout (CoordinatorLayout.java:869) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.support.v4 .view.ViewPager.onLayout (ViewPager.java:1767) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.LinearLayout. setChildFrame (LinearLayout.java:1649) en android.widget.LinearLayout.layoutVertical (LinearLayout.java:1507) en android.widget.LinearLayout.onLayout (LinearLayout.java:1420) en android. view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.FrameLayout.onLayout (FrameLayout.java:448) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.FrameLayout.onLayout (FrameLayout.java:448) en android.view.View.layout (View.java: 13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.LinearLayout.setChildFrame (LinearLayout.java:1649) en android.widget.LinearLayout.layoutVertical (LinearLayout.java:1507) en android. widget.LinearLayout.onLayout (LinearLayout.java:1420) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.FrameLayout.onLayout (FrameLayout.java:448) en android.view.View.layout (View.java:13754) en android.view.ViewGroup.layout (ViewGroup.java:4364) en android.widget.FrameLayout.onLayout (FrameLayout.java: 448) en android.view.View.layout (View.java:13754) en android.view.ViewGrou p.layout (Vi

Con la biblioteca de soporte AppCompat actual, puede usar la app:tint en la etiqueta ImageView que se AppCompatImageView como AppCompatImageView y manejará el cambio de estado correctamente.

En AppCompatImageView , puede ver que mImageHelper recibe una notificación del cambio de estado:

 @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (mBackgroundTintHelper != null) { mBackgroundTintHelper.applySupportBackgroundTint(); } if (mImageHelper != null) { mImageHelper.applySupportImageTint(); } } 

Actualmente, Android Studio da una advertencia sobre esto, pero puede suprimirlo de forma segura.