2

I am trying to update the tint of an ImageView programatically, and the colour I'm using is a selector that has different colours for when the view is enabled or disabled. When I try and use the suggested methods from other StackOverflow posts it set the enabled colour but does not update for views that are disabled

For example, I have the following four dots that are coloured red in XML, and I'm setting the bottom two to be green in code. The right two dots are disabled so I'd expect both to be the same disabled grey but as you can see the programatically set colour is always green

https://i.sstatic.net/tFpgp.png

How can I programatically update the tint of an ImageView so that it correctly follows the state in the selector?

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <!-- Also tried making these AppCompatImageViews -->
    <ImageView
        android:id="@+id/imgDot1"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:tint="@color/color_red_stateful"
        android:src="@drawable/ic_dot" />

    <ImageView
        android:id="@+id/imgDot2"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:tint="@color/color_red_stateful"
        android:src="@drawable/ic_dot" />
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imgDot3"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:tint="@color/color_red_stateful"
        android:src="@drawable/ic_dot" />

    <ImageView
        android:id="@+id/imgDot4"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:tint="@color/color_red_stateful"
        android:enabled="false"
        android:src="@drawable/ic_dot" />
</LinearLayout>
imgDot2.isEnabled = false
imgDot4.isEnabled = false

// Tried each of these in turn
ImageViewCompat.setImageTintList(imgDot3, ColorStateList.valueOf(resources.getColor(R.color.color_green_stateful)))
ImageViewCompat.setImageTintList(imgDot4, ColorStateList.valueOf(resources.getColor(R.color.color_green_stateful)))

imgDot3.setColorFilter(ContextCompat.getColor(this, R.color.color_green_stateful))
imgDot4.setColorFilter(ContextCompat.getColor(this, R.color.color_green_stateful))

imgDot3.imageTintList = ColorStateList.valueOf(resources.getColor(R.color.color_green_stateful))
imgDot4.imageTintList = ColorStateList.valueOf(resources.getColor(R.color.color_green_stateful))

imgDot3.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_green_stateful))
imgDot4.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.color_green_stateful))

color_red_stateful.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:color="#999"/>
    <item android:color="#F00"/>
</selector>

color_green_stateful.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:color="#999"/>
    <item android:color="#0F0"/>
</selector>

ic_dot.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#000"
        android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"/>
</vector>

2 Answers 2

3

You are using getColor method in every tried line, but this isn't proper, that's not color, that's selector (color_red_stateful and color_green_stateful files). use Resources or preferably ContextCompat class and its useful method getColorStateList

 ColorStateList colorStateList = ContextCompat.getColorStateList(this, R.color.your_color_selector);

this colorStateList should be set as imageTintList for desired ImageViews

btw. after setting above you may use view.invalidate() method for forcing immediate apply of changes (force redraw), but in most cases, also probably yours, this won't be needed

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, that's it thanks! We had an additional layer of complexity since these colours were being passed into custom views and being read as colours rather than colourStateLists, but that solved our issue
0

I am trying to update the tint of an ImageView programmatically, and the colour I'm using is a selector that has different colours for when the view is enabled or disabled

Option1:

As I see you already set android:tint for each view in your XML file.

so to do enable disable programmatically you need to update the views after enable or disable.

Set isEnabled to true or false first:

imgDot2.isEnabled = false
imgDot4.isEnabled = false

Invalidate views:

imgDot2.invalidate()
imgDot4.invalidate()

Then it will update the views based on your input.

No need to set setImageTintList or setColorFilter again in Activity.

Option2:

Want to set color programmatically then

ImageViewCompat.setImageTintList(imgDot2, ContextCompat.getColorStateList(this, R.color.color_green_stateful))
ImageViewCompat.setImageTintList(imgDot4, ContextCompat.getColorStateList(this, R.color.color_green_stateful))

Invalidate views:

imgDot2.invalidate()
imgDot4.invalidate()

Note: you must use app:tint instead of android:tint in your XML.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.