Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android imageview change tint to simulate button click

I have an imageview on which I have set a bitmap fetched from an url. On the imageview I have set an onClickListener which opens up a dialog.

I want to somehow change the tint (make it darker) when the imageview is pressed upon to provide a sort of button click like feel.

What do you suggest?

like image 997
Abhishek Avatar asked Jun 19 '12 06:06

Abhishek


People also ask

How do you make an ImageView clickable like a simple button?

You can make a view clickable, as a button, by adding the android:onClick attribute in the XML layout. For example, you can make an image act like a button by adding android:onClick to the ImageView .

Can ImageView be used as button?

We will be building a simple application in which we will be displaying an ImageView and when we click on that ImageView we will get into a new activity or simply we can say that we are going to use ImageView as a button to switch between different activities.

How do you make a picture act like a button?

You can turn any View , such as an ImageView , into a button by adding the android:onClick attribute in the XML layout. The image for the ImageView must already be stored in the drawable folder of your project.


2 Answers

happydude's answer is the most elegant way to handle this but unfortunately (as pointed out in the comments) the source code for ImageView only accepts an integer (solid colour). Issue 18220 has been around for a couple years addressing this, I've posted a workaround there that I'll summarize here:

Extend ImageView and wrap drawableStateChanged() with code that sets the tint based on the new state:

TintableImageView.java

package com.example.widgets;  import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.util.AttributeSet; import android.support.v7.widget.AppCompatImageView;  import com.example.R;  public class TintableImageView extends AppCompatImageView {      private ColorStateList tint;      public TintableImageView(Context context) {         super(context);     }      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);     }      private void init(Context context, AttributeSet attrs, int defStyle) {         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintableImageView, defStyle, 0);         tint = a.getColorStateList(R.styleable.TintableImageView_tintColorStateList);         a.recycle();     }      @Override     protected void drawableStateChanged() {         super.drawableStateChanged();         if (tint != null && tint.isStateful())             updateTintColor();     }          private void updateTintColor() {         int color = tint.getColorForState(getDrawableState(), 0);         setColorFilter(color);     }  } 

Define a custom attribute:

attrs.xml

<?xml version="1.0" encoding="UTF-8"?> <resources>      <declare-styleable name="TintableImageView">         <attr name="tintColorStateList" format="reference|color" />     </declare-styleable>  </resources> 

Use the widget and custom attribute with your local namespace instead of Android's:

example_layout.xml

<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:orientation="horizontal">      <com.example.widgets.TintableImageView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:src="@drawable/example"         android:clickable="true"         app:tintColorStateList="@color/color_selector"/>  </LinearLayout> 

You can then use a colour selector like happydude suggested:

color_selector.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">     <item android:state_pressed="true" android:color="@color/pressed_color"/>     <item android:color="#00000000"/> </selector> 
like image 72
Stephen Kidson Avatar answered Sep 24 '22 10:09

Stephen Kidson


One way would be to use a combination of a ColorFilter and a ColorStateList that contains your tint color for when the button is pressed. The xml for the ColorStateList in the res/color directory would look like this:

button_pressed.xml

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android">      <item android:state_pressed="true" android:color="@color/pressed_color"/>     <item android:color="#00000000"/>  </selector> 

where @color/pressed_color is your tint color (which should be partially transparent). Then in your ImageView subclass, you apply the color by overriding drawableStateChanged().

@Override protected void drawableStateChanged() {     super.drawableStateChanged();      ColorStateList list = getResources().getColorStateList(R.color.button_pressed);     int color = list.getColorForState(getDrawableState(), Color.TRANSPARENT);     setColorFilter(color);     invalidate(); } 

Any time the button's state changes, this code is called and will automatically set the tint as appropriate.

like image 21
happydude Avatar answered Sep 23 '22 10:09

happydude