I have imageview in my Android app that I am using like a button with the onClick event given, but as you might guess it is not giving imageview a clickable effect when clic
For defining the selector drawable choice
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@drawable/img_down" />
<item android:state_selected="false"
android:drawable="@drawable/img_up" />
</selector>
I have to use android:state_pressed instead of android:state_selected
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed ="true"
android:drawable="@drawable/img_down" />
<item android:state_pressed ="false"
android:drawable="@drawable/img_up" />
</selector>
I have a more beauty solution if you use background images :)
public static void blackButton(View button){
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xf0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
break;
}
}
return false;
}
});
}
Here's my solution, which, using "nineOldAndroids" library, supports old APIs too:
rootView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
v.setBackgroundResource(R.drawable.listview_normal);
ViewHelper.setAlpha(imageView, 1);
break;
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(0);
v.setBackgroundColor(getResources().getColor(R.color.listview_pressed));
ViewHelper.setAlpha(imageView, 0.75f);
break;
}
return false;
}
});
It assumes the rootView is the cell itself (the layout), and that it has a single imageView that you wish to be affected by the color that you wish to apply to the whole cell.
EDIT: if you wish, you can also extend ImageView to handle foreground, and set it to "?android:attr/selectableItemBackground". There is a library for this here and a tutorial on how to do it for any view you wish, here.
You can design different images for clicked/not clicked states and set them in the onTouchListener as follows
final ImageView v = (ImageView) findViewById(R.id.button0);
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.setImageBitmap(res.getDrawable(R.drawable.img_down));
break;
}
case MotionEvent.ACTION_CANCEL:{
v.setImageBitmap(res.getDrawable(R.drawable.img_up));
break;
}
}
return true;
}
});
The better choice is that you define a selector as follows
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@drawable/img_down" />
<item android:state_selected="false"
android:drawable="@drawable/img_up" />
</selector>
and select the image in the event:
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
return true;
}
});
This worked for me:
img.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
((ImageView)v).setImageAlpha(200);
break;
}
case MotionEvent.ACTION_MOVE:
{
// if inside bounds
if(event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight())
{
((ImageView)v).setImageAlpha(200);
}
else
{
((ImageView)v).setImageAlpha(255);
}
break;
}
case MotionEvent.ACTION_UP:
{
((ImageView)v).setImageAlpha(255);
}
}
return true;
}
});
@Edit: As Gunhan said there will be backward compatibility problem with setImageAlpha method. I used this method:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
Thanks for the help on this thread. However, you missed one thing...you need to handle the ACTION_CANCEL as well. If you don't then you might not properly restore the alpha value of the ImageView in the event that a parent view in the view hierarchy intercepts a touch event (think a ScrollView wrapping you ImageView).
Here is a complete class that is based off the above class but takes care of the ACTION_CANCEL as well. It uses an ImageViewCompat helper class to abstract the differences in the pre-post JellyBean API.
public class ChangeAlphaOnPressedTouchListener implements OnTouchListener {
private final float pressedAlpha;
public ChangeAlphaOnPressedTouchListener(float pressedAlpha) {
this.pressedAlpha = pressedAlpha;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView iv = (ImageView) v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ImageViewCompat.setAlpha(iv, pressedAlpha);
break;
case MotionEvent.ACTION_MOVE:
if (isInsideViewBounds(v, event)) {
ImageViewCompat.setAlpha(iv, pressedAlpha);
} else {
ImageViewCompat.setAlpha(iv, 1f);
}
break;
case MotionEvent.ACTION_UP:
ImageViewCompat.setAlpha(iv, 1f);
break;
case MotionEvent.ACTION_CANCEL:
ImageViewCompat.setAlpha(iv, 1f);
}
return false;
}
private static boolean isInsideViewBounds(View v, MotionEvent event) {
return event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0
&& event.getY() < v.getHeight();
}
}