Handling click events on a drawable within an EditText Handling click events on a drawable within an EditText android android

Handling click events on a drawable within an EditText


Actually you don't need to extend any class. Let's say I have an EditText editComment with a drawableRight

editComment.setOnTouchListener(new OnTouchListener() {    @Override    public boolean onTouch(View v, MotionEvent event) {        final int DRAWABLE_LEFT = 0;        final int DRAWABLE_TOP = 1;        final int DRAWABLE_RIGHT = 2;        final int DRAWABLE_BOTTOM = 3;        if(event.getAction() == MotionEvent.ACTION_UP) {            if(event.getRawX() >= (editComment.getRight() - editComment.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {                // your action here                return true;            }        }        return false;    }});

we getRawX() because we want to get the actual position of touch on screen, not relative to parent.

To get left side click

if(event.getRawX() <= (editComment.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) 


Very, very good, thanks to everyone who contributed to this discussion. So if you don't want to deal with inconvenience of extending the class you can do the following (implemented for the right drawable only)

this.keyword = (AutoCompleteTextView) findViewById(R.id.search);this.keyword.setOnTouchListener(new RightDrawableOnTouchListener(keyword) {        @Override        public boolean onDrawableTouch(final MotionEvent event) {            return onClickSearch(keyword,event);        }    });private boolean onClickSearch(final View view, MotionEvent event) {    // do something    event.setAction(MotionEvent.ACTION_CANCEL);    return false;}

And here's bare-bone listener implementation based on @Mark's answer

public abstract class RightDrawableOnTouchListener implements OnTouchListener {    Drawable drawable;    private int fuzz = 10;    /**     * @param keyword     */    public RightDrawableOnTouchListener(TextView view) {        super();        final Drawable[] drawables = view.getCompoundDrawables();        if (drawables != null && drawables.length == 4)            this.drawable = drawables[2];    }    /*     * (non-Javadoc)     *      * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)     */    @Override    public boolean onTouch(final View v, final MotionEvent event) {        if (event.getAction() == MotionEvent.ACTION_DOWN && drawable != null) {            final int x = (int) event.getX();            final int y = (int) event.getY();            final Rect bounds = drawable.getBounds();            if (x >= (v.getRight() - bounds.width() - fuzz) && x <= (v.getRight() - v.getPaddingRight() + fuzz)                    && y >= (v.getPaddingTop() - fuzz) && y <= (v.getHeight() - v.getPaddingBottom()) + fuzz) {                return onDrawableTouch(event);            }        }        return false;    }    public abstract boolean onDrawableTouch(final MotionEvent event);}


Consider the following. It's not the most elegant solution but it works, I just tested it.

  1. Create a customized EditText class CustomEditText.java:

    import android.content.Context;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.EditText;public class CustomEditText extends EditText{  private Drawable dRight;  private Rect rBounds;  public CustomEditText(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);  }  public CustomEditText(Context context, AttributeSet attrs) {    super(context, attrs);  }  public CustomEditText(Context context) {    super(context);  }  @Override  public void setCompoundDrawables(Drawable left, Drawable top,      Drawable right, Drawable bottom)  {    if(right !=null)    {      dRight = right;    }    super.setCompoundDrawables(left, top, right, bottom);  }  @Override  public boolean onTouchEvent(MotionEvent event)  {    if(event.getAction() == MotionEvent.ACTION_UP && dRight!=null)    {      rBounds = dRight.getBounds();      final int x = (int)event.getX();      final int y = (int)event.getY();      //System.out.println("x:/y: "+x+"/"+y);      //System.out.println("bounds: "+bounds.left+"/"+bounds.right+"/"+bounds.top+"/"+bounds.bottom);      //check to make sure the touch event was within the bounds of the drawable      if(x>=(this.getRight()-rBounds.width()) && x<=(this.getRight()-this.getPaddingRight())          && y>=this.getPaddingTop() && y<=(this.getHeight()-this.getPaddingBottom()))      {        //System.out.println("touch");        this.setText("");        event.setAction(MotionEvent.ACTION_CANCEL);//use this to prevent the keyboard from coming up      }    }    return super.onTouchEvent(event);  }  @Override  protected void finalize() throws Throwable  {    dRight = null;    rBounds = null;    super.finalize();  }}
  2. Change your layout XML to this (where com.example is your actual project package name):

    <com.example.CustomEditText    android:id="@+id/txtsearch"    …    android:layout_gravity="center_vertical"    android:background="@layout/shape"    android:hint="Enter place,city,state"    android:drawableRight="@drawable/cross" />
  3. Finally, add this (or something similar) to your activity:

    CustomEditText et = (CustomEditText) this.findViewById(R.id.txtsearch);…

I might be a bit off with the calculation of the touch bounds for the nested drawable but you get the idea.

I hope this helps.