How to use selector to display image in android

I want to color my tabhost icons with xml, instead of doing it programmatically (I still couldn’t do it) ... So, I found this thread on SO: Changing the Android image style to simulate a button click

This seems like a pretty good solution, but I couldn’t adapt it correctly in my project ... I made the following changes:

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

I was also unable to reference @drawable/selector.xml on android:tint , so I did this in colors.xml:

 <?xml version="1.0" encoding="utf-8"?> <resources> <color name="azulPadrao">#2e7cb4</color> <drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable> </resources> 

My selector:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:tint="#007AFF" /> <item android:state_focused="true" android:tint="#007AFF" /> <item android:state_pressed="true" android:tint="#007AFF" /> <item android:tint="#929292" /> </selector> 

My tab layout:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:id="@+id/TabLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:background="@drawable/tab_bg_selector"> <com.myapp.TintableImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" android:layout_gravity="center" android:tint="@drawable/tab_icon_selector"/> <TextView android:id="@+id/TabTextView" android:text="Text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@drawable/tab_text_selector" android:textSize="10dip" android:textStyle="bold" android:layout_marginTop="2dip"/> </LinearLayout> 

Any suggestions? thanks in advance

[EDIT] I was getting a NumberFormatException to use android:tint when the correct one was app:tint (after installing xmlns:app="http://schemas.android.com/apk/res/com.myapp" ) ... but now I think I am using my selector incorrectly because the icons are all black, regardless of state ... I tried to set <drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable> from colors.xml, did not work

[/ EDIT]

+17
android android-imageview
Oct 21 '13 at 16:36
source share
6 answers

In regards to my solution, in https://stackoverflow.com/a/3/9/9/11/12/30/... there are a few things you are missing:

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 () must be redefined to change the hue when the state of an element changes.

I'm not sure if linking to drawable from drawable may cause a problem, but you can just move your selector.xml to the "/ res / color" folder to link to it using "@ color / selector.xml", (aapt combines both /res/values/colors.xml and the / res / color folder).

+11
Oct 22 '13 at 20:32
source share

If you are using API 21+, you can easily do this in XML using the selector and tint :

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="true"> <bitmap android:src="@drawable/ic_settings_grey" android:tint="@color/primary" /> </item> <item android:drawable="@drawable/ic_settings_grey"/> </selector> 
+22
Feb 05 '15 at 20:58
source share

I implemented this using DrawableCompat from the Android v4 support library.

With a regular ImageButton (which is subclassed by ImageView , so this information also applies to ImageView s) using the black icon from the material icon collection :

 <ImageButton android:id="@+id/button_add" android:src="@drawable/ic_add_black_36dp" android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/title_add_item" /> 

This is the utility method I created:

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

Where res/color/button_colour.xml is a selector that changes the color of the icon from red to translucent red when the button is pressed:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="false" android:color="@color/red" /> <item android:color="@color/red_alpha_50pc" /> </selector> 

After ImageButton was overstated in my onCreate() method, I simply call the tintButton(...) helper method once for each button.




I tested this on Android 4.1 (my minSdkVersion ) and 5.0 devices, but DrawableCompat should return to Android 1.6.

+13
Aug 05 '15 at 15:10
source share

In support library 22.1, we can use DrawableCompat to draw tint, a level 4 + API

DrawableCompat.wrap (Drawable) and setTint (), setTintList () and setTintMode () will work: there is no need to create and maintain separate drawings just to support multiple colors!

+10
Apr 22 '15 at 6:59
source share

In the current AppCompat support library, you can use the app:tint tag app:tint on ImageView , which will pump as AppCompatImageView and correctly edit the state.

In the AppCompatImageView you can see that mImageHelper notified of a state change:

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

Android Studio currently gives a warning about this, but you can safely suppress it.

+3
Jun 19 '17 at 15:17
source share

I agree with @Dreaming in the code and I will give an example.

ic_up_small

 <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/comment_count_selected_color" android:state_selected="true" /> <item android:color="@color/comment_count_text_color"/> </selector> 

Layout / item_post_count_info.xml

 <android.support.v7.widget.AppCompatImageView android:id="@+id/post_upvote_icon" android:layout_width="14dp" android:layout_height="14dp" android:layout_marginLeft="17dp" app:srcCompat="@drawable/ic_up_small" app:tint="@color/post_up_color"/> 

Note: we must use app: tint instead of android: tint.

My support library version is 26.0.2.

application / 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' 

If we use android: tint, it will work, and the log will be like this:

E / AndroidRuntime: FATAL EXCEPTION: main android.view.InflateException: binary line of XML file # 0: error inflating class on android.view.LayoutInflater.createView (LayoutInflater.java:613) in android.view.LayoutInflater.createViewFromTag (LayoutInflater. java: 687) on android.view.LayoutInflater.rilflate (LayoutInflater.java:746) on android.view.LayoutInflater.inflate (LayoutInflater.javaced89) on android.view.LayoutInflater.inflate (LayoutInflater.java opin96) in com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.Create (PostCountInfoViewHolder.java:29) in com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.Create (PostCountInfoViewHolder.java:25) in com.opera.six .collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.java:39) in com.opera.six.collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.java:19) in android.support.v7.widget.RecyclerView $ Adapter.createViewHolder (RecyclerView.ava : 6493) in android.support.v7.widget.RecyclerView $ Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:5680) in android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java:5563) in android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.java=559) in android.support.v7.widget .LinearLayoutManager $ LayoutState.next (LinearLayoutManager.java:2229) in android.support.v7.widget.LinearLayoutManager.layoutChunk (LinearLayoutManager.java:1556) in android.support.v7.widget.LinearLayoutMaragerjill15an Linear ) in android.support.v7.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.java:608) in android.support.v7.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.javahaps693) in android.support.v7.widget.RecyclerView.dispatchLayout (RecyclerView.java:3410) in android.support.v7.widget.RecyclerView.onLayout RecyclerView.java:3962) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) in android.support.v4.widget.SwipeRefreshLayout.onLayout (SwipeRefreshLayout .java: 610) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGro up.java:4364) in android.support.design.widget.HeaderScrollingViewBehavior.layoutChild (HeaderScrollingViewBehavior.java:132) in android.support.design.widget.ViewOffsetBehavior.onLayoutChild (ViewOffsetBehavior.java:42) in android.support. .widget.AppBarLayout $ ScrollingViewBehavior.onLayoutChild (AppBarLayout.java:1361) in android.support.design.widget.CoordinatorLayout.onLayout (CoordinatorLayout.java:869) in android.view.View.layout (View.java:13754) android.view.ViewGroup.layout (ViewGroup.java:4364) in android.support.v4.view.ViewPager.onLayout (ViewPager.java:1767) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget.LinearLayout.setChildFrame (LinearLayout.java:1649) at android.widget.LinearLayout.layoutVertical (LinearLayout.java:1507) on android.widget.LinearLayout.onLayout (LinearLayout.java:1420) in androidview.View .layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget.FrameLayout.onLayout (FrameLayout.java:448) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget. FrameLayout.onLayout (FrameLayout.java:448) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget.LinearLayout.setChildFrame (LinearLayout .java: 1649) at android.widget.LinearLayout.layoutVertical (LinearLayout.java:1507) on android.widget.LinearLayout.onLayout (LinearLayout.java:1420) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget. FrameLayout.onLayout (FrameLayout.java:448) in android.view.View.layout (View.java:13754) in android.view.ViewGroup.layout (ViewGroup.java:4364) on android.widget.FrameLayout.onLayout (FrameLayout .java: 448) in android.view.View.layout (View.java:13754) at android.view.ViewGroup.layout (Vi

+3
Nov 15 '17 at 12:22
source share



All Articles