17

I set a image as Button backgroud,but Button has no highlight when click it. Is there any way to solve it.

Nick
  • 241
  • 1
  • 2
  • 9
  • 1
    Refer this [link](http://stackoverflow.com/questions/4125774/android-button-set-onclick-background-image-change-with-xml/4125877#4125877) – David Nov 10 '10 at 10:36

7 Answers7

21

If this is an ImageButton and you don't want to use several drawable for each pressed/unpressed state you could use the color filter attibute of images. This solution is similar to the one used by Omar.

Create an OnTouchListener modifying the color filter on touch.

public class ButtonHighlighterOnTouchListener implements OnTouchListener {

  final ImageButton imageButton;

  public ButtonHighlighterOnTouchListener(final ImageButton imageButton) {
    super();
    this.imageButton = imageButton;
  }

  public boolean onTouch(final View view, final MotionEvent motionEvent) {
    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
      //grey color filter, you can change the color as you like
      imageButton.setColorFilter(Color.argb(155, 185, 185, 185));
    } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
      imageButton.setColorFilter(Color.argb(0, 185, 185, 185)); 
    }
    return false;
  }

}

Assign this listener to your button:

  myButton = (ImageButton) findViewById(R.id.myButton);
  myButton.setOnTouchListener(new ButtonHighlighterOnTouchListener(myButton));

Update

Improved class to apply highlighter to ImageView, ImageButton or TextView via its compound Drawable.

public class ButtonHighlighterOnTouchListener implements OnTouchListener {

  private static final int TRANSPARENT_GREY = Color.argb(0, 185, 185, 185);
  private static final int FILTERED_GREY = Color.argb(155, 185, 185, 185);

  ImageView imageView;
  TextView textView;

  public ButtonHighlighterOnTouchListener(final ImageView imageView) {
    super();
    this.imageView = imageView;
  }

  public ButtonHighlighterOnTouchListener(final TextView textView) {
    super();
    this.textView = textView;
  }

  public boolean onTouch(final View view, final MotionEvent motionEvent) {
    if (imageView != null) {
      if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
        imageView.setColorFilter(FILTERED_GREY);
      } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
        imageView.setColorFilter(TRANSPARENT_GREY); // or null
      }
    } else {
      for (final Drawable compoundDrawable : textView.getCompoundDrawables()) {
        if (compoundDrawable != null) {
          if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
            // we use PorterDuff.Mode. SRC_ATOP as our filter color is already transparent
            // we should have use PorterDuff.Mode.LIGHTEN with a non transparent color
            compoundDrawable.setColorFilter(FILTERED_GREY, PorterDuff.Mode.SRC_ATOP);
          } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
            compoundDrawable.setColorFilter(TRANSPARENT_GREY, PorterDuff.Mode.SRC_ATOP); // or null
          }
        }
      }
    }
    return false;
  }

}
L. G.
  • 9,642
  • 7
  • 56
  • 78
13

See here

And also here for Romain Guy's answer:

In res/drawable, create a file called for instance mybutton_background.xml and put something like this inside:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="true" android:state_pressed="false" 
        android:drawable="@drawable/button_background_focus" /> 

    <item android:state_focused="true" android:state_pressed="true" 
        android:drawable="@drawable/button_background_pressed" /> 

    <item android:state_focused="false" android:state_pressed="true" 
        android:drawable="@drawable/button_background_pressed" /> 

    <item android:drawable="@drawable/button_background_normal" /> 

</selector> 

Then set this drawable as the background of your button with android:background="@drawable/mybutton_background"

madlymad
  • 6,367
  • 6
  • 37
  • 68
Lior Iluz
  • 26,213
  • 16
  • 65
  • 114
  • You can use a Proxy server to get there. Anyway, updated my answer with the solution (the one written by Romain Guy) – Lior Iluz Nov 10 '10 at 09:18
11

To get you to the correct resource here is the documentation of the StateList Drawable. You just create and define it in your res/drawable subdirectory and set it as your buttons background.

Octavian Helm
  • 39,405
  • 19
  • 98
  • 102
4

if you are using

<Button 
  ------------------
android:background="@drawable/youimage"
>

Then as it is better to declare new a new xml. with the image you can specify image for each event state. as Octavian says
and you can you can set this xml as you background

if your xml is 'res/drawable/abc.xml' then set background as

android:background="@drawable/abc"

You can also use ImageButton

<ImageButton
----------------------
android:src="@drawable/youimage" 
 />

The benefit for ImageButton is that, no need of different image for highlight.

Labeeb Panampullan
  • 34,521
  • 28
  • 94
  • 112
3

Try this to get a poor man's highlight effect without the need of making multiple copies of your images. Set the alpha value 0.8 to a desired value:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageButton;

public class EAImageButton extends ImageButton {

    public EAImageButton(Context context) {
        super(context);
        // TODO Auto-generated constructor stub

    }
    public EAImageButton(Context context, AttributeSet attrs){
        super(context,attrs);
    }
    public EAImageButton(Context context, AttributeSet attrs, int defStyle){
        super(context,attrs,defStyle);
    }
    public void setImageResource (int resId){
        super.setImageResource(resId);
    }
    @Override
    public boolean onTouchEvent(MotionEvent e){
        if(e.getAction() == MotionEvent.ACTION_DOWN){
            this.setAlpha((int)( 0.8 * 255));
        }else if(e.getAction() == MotionEvent.ACTION_UP){
            this.setAlpha((int)( 1.0 * 255));
        }

        return super.onTouchEvent(e);

    }

}
Omar
  • 463
  • 3
  • 11
2

I made it by override Button class

public class MButton extends Button {
public MButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
}

public MButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub

}

public MButton(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}

//define style
public void setPressedBg(Integer[] mImageIds) {
    StateListDrawable bg = new StateListDrawable();
    Drawable normal = this.getResources().getDrawable(mImageIds[0]);
    Drawable selected = this.getResources().getDrawable(mImageIds[1]);
    Drawable pressed = this.getResources().getDrawable(mImageIds[2]);

    bg.addState(View.PRESSED_ENABLED_STATE_SET, pressed);
    bg.addState(View.ENABLED_FOCUSED_STATE_SET, selected);
    bg.addState(View.ENABLED_STATE_SET, normal);
    bg.addState(View.FOCUSED_STATE_SET, selected);
    bg.addState(View.EMPTY_STATE_SET, normal);
    this.setBackgroundDrawable(bg);
}

//define style
public void setPressedBg(Integer p1,Integer p2,Integer p3) {
    StateListDrawable bg = new StateListDrawable();
    Drawable normal = this.getResources().getDrawable(p1);
    Drawable selected = this.getResources().getDrawable(p2);
    Drawable pressed = this.getResources().getDrawable(p3);

    bg.addState(View.PRESSED_ENABLED_STATE_SET, pressed);
    bg.addState(View.ENABLED_FOCUSED_STATE_SET, selected);
    bg.addState(View.ENABLED_STATE_SET, normal);
    bg.addState(View.FOCUSED_STATE_SET, selected);
    bg.addState(View.EMPTY_STATE_SET, normal);
    this.setBackgroundDrawable(bg);
}

}

in my main()

toneButton.setPressedBg(R.drawable.button_tone_protrait_pipa,
            R.drawable.button_tone_protrait_pipa1,
            R.drawable.button_tone_protrait_pipa1);
Nick
  • 241
  • 1
  • 2
  • 9
0

Use View.setFocusableInTouchMode or android:focusableInTouchMode. In this case use this piece for your Button, either in XML or in the code itself. For details refer :http://developer.android.com/reference/android/view/View.html

Gaurav Navgire
  • 780
  • 5
  • 17
  • 29
  • I'm China,there is GFW here,so I can't get http://developer.android.com/ thanks anyway – Nick Nov 10 '10 at 08:31