A good example of this is either on the Twitter launch screen (the screen with the large icons that is seen when the application is first launch) or even just look at the ap
You need to assign the src
attribute of the ImageView
a state list drawable. In other words, that state list would have a different image for selected, pressed, not selected, etc. - that's how the Twitter App does it.
So if you had an ImageView:
<ImageView style="@style/TitleBarLogo"
android:contentDescription="@string/description_logo"
android:src="@drawable/title_logo" />
The src drawable (title_logo.xml) would look like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/title_logo_pressed"/>
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/title_logo_pressed"/>
<item android:state_focused="true" android:drawable="@drawable/title_logo_selected"/>
<item android:state_focused="false" android:state_pressed="false" android:drawable="@drawable/title_logo_default"/>
</selector>
The Google IO Schedule app has a good example of this.
My solution, custom attribute for ImageView :
https://github.com/henrychuangtw/Android-ImageView-hover
Step 1 : declare-styleable
<declare-styleable name="MyImageViewAttr">
<attr name="hover_res" format="reference" />
</declare-styleable>
Step 2 : custom ImageView
public class MyImageView extends ImageView {
int resID, resID_hover;
public MyImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
if(resID_hover != -1){
int[] attrsArray = new int[] {
android.R.attr.src
};
TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
resID = ta.getResourceId(0 , View.NO_ID);
ta.recycle();
setOnTouchListener(listener_onTouch);
}
array.recycle();
}
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyImageViewAttr);
resID_hover = array.getResourceId(R.styleable.MyImageViewAttr_hover_res, -1);
if(resID_hover != -1){
int[] attrsArray = new int[] {
android.R.attr.src
};
TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
resID = ta.getResourceId(0 , View.NO_ID);
ta.recycle();
setOnTouchListener(listener_onTouch);
}
array.recycle();
}
OnTouchListener listener_onTouch = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setImageResource(resID_hover);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
setImageResource(resID);
break;
default:
break;
}
return false;
}
};
}
Step 3 : declare myattr : xmlns:myattr="http://schemas.android.com/apk/res-auto" in layout xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myattr="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
Step 4 : set myattr:hover_res for MyImageView
<dev.henrychuang.component.MyImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
myattr:hover_res="@drawable/icon_home_h"
android:src="@drawable/icon_home"/>
I am using android:state_selected="true"
for the state of imageView.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_enable" android:state_selected="true" />
<item android:drawable="@drawable/ic_disable" android:state_selected="false" />
<!--for default-->
<item android:drawable="@drawable/ic_enable" />
</selector>
use img_view.setSelected(true)
OR img_view.setSelected(false)
for change state of image in java/kotlin code.
For displaying dynamic images you can use a LayerDrawable for the image source.
LayerDrawable d = new LayerDrawable(new Drawable[]{new BitmapDrawable(myBmp), getResources().getDrawable(R.drawable.my_selector_list)});
imageView.setImageDrawable(d);
I put together small library that should help with that: https://github.com/noveogroup/Highlightify
Basically it creates selector in runtime, and it should be really easy to use. Though, focused state not supported yet...
This is an extension of mklimek. I couldn't make it work properly from his snippet. I edited a bit
ImageView testImage = (ImageView)findViewById(R.id.imageView);
testImage.setOnTouchListener(listener);
View.OnTouchListener listener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView image = (ImageView) v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
image.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
image.invalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
//clear the overlay
image.getDrawable().clearColorFilter();
image.invalidate();
break;
}
}
return true;
}
};