Handling click events on a drawable within an EditText
Solution 1
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()))
Solution 2
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);
}
Solution 3
Consider the following. It's not the most elegant solution but it works, I just tested it.
Create a customized
EditText
classCustomEditText.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(); } }
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" />
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.
Solution 4
I created a useful abstract class DrawableClickListener which implements OnTouchListener.
In addition to the DrawableClickListener class, I also created 4 additional abstract classes which extend the DrawableClickListener class and handle the clicking of the drawable area for the correct quadrant.
- LeftDrawableClickListener
- TopDrawableClickListener
- RightDrawableClickListener
- BottomDrawableClickListener
Point to Consider
One thing to consider is that the images are not resized if done this way; thus the images must be scaled correctly before being put into the res/drawable folder(s).
If you define a LinearLayout containing an ImageView and a TextView, it's a lot easier to manipulate the size of the image being displayed.
activity_my.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="replace this with a variable"
android:textSize="30sp"
android:drawableLeft="@drawable/my_left_image"
android:drawableRight="@drawable/my_right_image"
android:drawablePadding="9dp" />
</RelativeLayout>
MyActivity.java
package com.company.project.core;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MyActivity extends Activity
{
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_my );
final TextView myTextView = (TextView) this.findViewById( R.id.myTextView );
myTextView.setOnTouchListener( new DrawableClickListener.LeftDrawableClickListener(myTextView)
{
@Override
public boolean onDrawableClick()
{
// TODO : insert code to perform on clicking of the LEFT drawable image...
return true;
}
} );
myTextView.setOnTouchListener( new DrawableClickListener.RightDrawableClickListener(myTextView)
{
@Override
public boolean onDrawableClick()
{
// TODO : insert code to perform on clicking of the RIGHT drawable image...
return true;
}
} );
}
}
DrawableClickListener.java
package com.company.project.core;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
/**
* This class can be used to define a listener for a compound drawable.
*
* @author Matthew Weiler
* */
public abstract class DrawableClickListener implements OnTouchListener
{
/* PUBLIC CONSTANTS */
/**
* This represents the left drawable.
* */
public static final int DRAWABLE_INDEX_LEFT = 0;
/**
* This represents the top drawable.
* */
public static final int DRAWABLE_INDEX_TOP = 1;
/**
* This represents the right drawable.
* */
public static final int DRAWABLE_INDEX_RIGHT = 2;
/**
* This represents the bottom drawable.
* */
public static final int DRAWABLE_INDEX_BOTTOM = 3;
/**
* This stores the default value to be used for the
* {@link DrawableClickListener#fuzz}.
* */
public static final int DEFAULT_FUZZ = 10;
/* PRIVATE VARIABLES */
/**
* This stores the number of pixels of "fuzz" that should be
* included to account for the size of a finger.
* */
private final int fuzz;
/**
* This will store a reference to the {@link Drawable}.
* */
private Drawable drawable = null;
/* CONSTRUCTORS */
/**
* This will create a new instance of a {@link DrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this {@link DrawableClickListener}
* is associated with.
* @param drawableIndex
* The index of the drawable that this
* {@link DrawableClickListener} pertains to.
* <br />
* <i>use one of the values:
* <b>DrawableOnTouchListener.DRAWABLE_INDEX_*</b></i>
*/
public DrawableClickListener( final TextView view, final int drawableIndex )
{
this( view, drawableIndex, DrawableClickListener.DEFAULT_FUZZ );
}
/**
* This will create a new instance of a {@link DrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this {@link DrawableClickListener}
* is associated with.
* @param drawableIndex
* The index of the drawable that this
* {@link DrawableClickListener} pertains to.
* <br />
* <i>use one of the values:
* <b>DrawableOnTouchListener.DRAWABLE_INDEX_*</b></i>
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public DrawableClickListener( final TextView view, final int drawableIndex, final int fuzz )
{
super();
this.fuzz = fuzz;
final Drawable[] drawables = view.getCompoundDrawables();
if ( drawables != null && drawables.length == 4 )
{
this.drawable = drawables[drawableIndex];
}
}
/* OVERRIDDEN PUBLIC METHODS */
@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 ( this.isClickOnDrawable( x, y, v, bounds, this.fuzz ) )
{
return this.onDrawableClick();
}
}
return false;
}
/* PUBLIC METHODS */
/**
*
* */
public abstract boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz );
/**
* This method will be fired when the drawable is touched/clicked.
*
* @return
* <code>true</code> if the listener has consumed the event;
* <code>false</code> otherwise.
* */
public abstract boolean onDrawableClick();
/* PUBLIC CLASSES */
/**
* This class can be used to define a listener for a <b>LEFT</b> compound
* drawable.
* */
public static abstract class LeftDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link LeftDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link LeftDrawableClickListener} is associated with.
*/
public LeftDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_LEFT );
}
/**
* This will create a new instance of a
* {@link LeftDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link LeftDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public LeftDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_LEFT, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getPaddingLeft() + drawableBounds.width() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>TOP</b> compound
* drawable.
* */
public static abstract class TopDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a {@link TopDrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this
* {@link TopDrawableClickListener} is associated with.
*/
public TopDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_TOP );
}
/**
* This will create a new instance of a {@link TopDrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this
* {@link TopDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public TopDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_TOP, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getPaddingTop() + drawableBounds.height() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>RIGHT</b> compound
* drawable.
* */
public static abstract class RightDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link RightDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link RightDrawableClickListener} is associated with.
*/
public RightDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_RIGHT );
}
/**
* This will create a new instance of a
* {@link RightDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link RightDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public RightDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_RIGHT, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getWidth() - view.getPaddingRight() - drawableBounds.width() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>BOTTOM</b> compound
* drawable.
* */
public static abstract class BottomDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link BottomDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link BottomDrawableClickListener} is associated with.
*/
public BottomDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_BOTTOM );
}
/**
* This will create a new instance of a
* {@link BottomDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link BottomDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public BottomDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_BOTTOM, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getHeight() - view.getPaddingBottom() - drawableBounds.height() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
}
Solution 5
Its very simple. Lets say you have a drawable on left side of your EditText 'txtsearch'. Following will do the trick.
EditText txtsearch = (EditText) findViewById(R.id.txtsearch);
txtsearch.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() <= txtsearch.getTotalPaddingLeft()) {
// your action for drawable click event
return true;
}
}
return false;
}
});
If you want for right drawable change the if statement to:
if(event.getRawX() >= txtsearch.getRight() - txtsearch.getTotalPaddingRight())
Similarly, you can do it for all compound drawables.
txtsearch.getTotalPaddingTop()
txtsearch.getTotalPaddingBottom()
This method call returns all the padding on that side including any drawables. You can use this even for TextView, Button etc.
Click here for reference from android developer site.
Related videos on Youtube
Manikandan
Updated on April 08, 2022Comments
-
Manikandan about 2 years
I have added an image right of the text in an
EditText
widget, using the following XML:<EditText android:id="@+id/txtsearch" ... android:layout_gravity="center_vertical" android:background="@layout/shape" android:hint="Enter place,city,state" android:drawableRight="@drawable/cross" />
But I want to clear the
EditText
when the embedded image is clicked. How can I do this?-
Hardik4560 almost 10 yearsPossible duplicate of stackoverflow.com/questions/13135447/…
-
Hawklike almost 2 yearsIf you are using
TextInputLayout
see stackoverflow.com/a/65940540/9723204. It's simple and elegant.
-
-
Thiago over 12 yearsIt seems your code is not working, I have just tested and nothing happens when I touch the drawable.
-
Bob Barbara almost 12 yearsActually, I have heard that modifying the MotionEvent is discouraged practice, leading to undefined behaviour that would likely break on different platforms, so perhaps a better solution could be stackoverflow.com/a/6235602
-
Maksim Dmitriev over 11 years@RyanM, I used
TextView
instead ofEditText
. I took the code and if I click on theTextView
(not the icon but on any space on theTextView
), the methodonTouchEvent(MotionEvent event)
is called. So, I can implementOnClickListener
for a usualTextView
without any additional classes such asCustomEditText
-
Vino over 11 years@RyanM, Instead of using
this.getRight()-rBounds.width()
why not usethis.getMeasuredWidth() - this.getCompoundPaddingRight()
? Wouldn't it take care of drawable's padding and also get rid of the drawable's bound? -
André about 11 yearsYou should add v.getLeft() to x and v.getTop() to y in order to get the correct position.
-
Speedy almost 11 yearsActually you should replace
v.getRight()
byv.getWidth()
. -
user1940676 over 10 yearsWhat about drawableLeft??
-
Admin over 10 yearsWhere did your onClickSearch method receive it's event?
-
Qadir Hussain over 10 years@RyanM how to change the image on touch of cross button click event?
-
Qadir Hussain over 10 years@user2848783 how to set this in my left drawable?
-
Pratik Butani over 10 yearsWorking after changed
event.getRawX()
instead ofevent.getX()
@AngeloS -
tomurka almost 10 yearsOne note: replace "return false;" to "return true;" otherwise after ACTION_DOWN -> ACTION_UP will not be fired.
-
RaB over 9 yearsnote that your fuzz factor should scale with the DPI, 10px in ldpi is something completely different from 10px in xxhdpi.
-
Paul Verest over 9 yearsa bit improved answer at stackoverflow.com/questions/23184120/…
-
gonzalomelov about 9 yearsYou have add "- v.getPaddingLeft()" to the first part of the if "x >= (v.getRight() - bounds.width() - fuzz)".
-
kassim about 9 yearsIf you add padding you need to count that in as well as the
getRight()
gets the right of the TextView, which won't be the right of the drawable if there's padding. Adding- editComment.getPaddingRight()
to the end of yourif
statement should work. -
Mansukh Ahir almost 9 years
public final float getRawX ()
Returns the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views. -
Chad Bingham over 8 yearsYou should check for negative.
.width()
does not check if it is returning a positive number. I just wrapped it withwidth = Math.abs(width);
-
Юрій Мазуревич over 8 yearsWhat is fuzz for? Please clarify.
-
Bianca Daniciuc over 8 yearsI think this is a fine answer, except the part where true is returned everywhere. I'd suggest to return true only when the event needs to be consumed (the touch gesture happened in the right area).
-
C0D3LIC1OU5 over 8 yearsUsed
RelativeLayout
to achieve proper positioning, just seems less convoluted than other solutions, and far less code to maintain. -
Fletcher Johns over 8 yearsThis does not work if the EditText's parent is not aligned with the left of the screen. You should use event.getX() instead of event.getRawX() and use editText.getWidth() instead of editText.getRight()
-
Tomask about 8 yearsCustom versions of
EditText
do not support proper widgets tinting when using appcompat on pre-lollipop devices. UseAppCompatEditText
as a parent class of your custom EditText -
Thunder Dragon over 7 yearsIn my case it is not working! Here getBounds()
returns Rect(0, 0 - -1, -1)
. Does anyone have any clue why this is happening? -
ban-geoengineering over 7 yearsIt looks like
fuzz
effectively makes the tappable area a bit larger, making it easier to tap the small drawable. -
Glenn over 6 yearsThis worked for me but I had to use getX() instead of getRawX(). I think getRawX() only works if the view is on the left edge of the screen.
-
Sotti over 6 yearsThe calculation of the positions is wrong. Is mixing absolute coordinates "getRawX()", with relative ones like "getRight()"
-
Sotti over 6 yearsThe problem with this approach is that falls apart as soon as you start changing the text size on the EditText. You might think that's just on the developer's side but it's not as far as the devices have text size in settings.You can avoid this using dp instead of sp on the EditText but it just makes things worse. The other problems are things like handling multiline EditTexts.
-
Sotti over 6 yearsThis is mixing absolute positions "getRawX" with relative positions "getRight". If you set a right or left margin on the editText you'll see how this breaks as the click is triggered on wrong coordinates.
-
Sotti over 6 yearsThe problem with this approach is that falls apart as soon as you start changing the text size on the EditText. You might think that's just on the developer's side but it's not as far as the devices have text size in settings.You can avoid this using dp instead of sp on the EditText but it just makes things worse. The other problems are things like handling multiline EditTexts
-
Sotti over 6 yearsIt's a little bit confusing that s TouchListener is handling the drawable visibility and the clear action itself. That's not a touch listener responsibility and the name of the class is misleading. As well as you are calculating relative positions is not necessary to remove margins from the equation. getRight - width will do it.
-
Sotti over 6 yearsThe problem with this approach is that falls apart as soon as you start changing the text size on the EditText. You might think that's just on the developer's side but it's not as far as the devices have text size in settings.You can avoid this using dp instead of sp on the EditText but it just makes things worse. The other problems are things like handling multiline EditTexts.
-
Sotti over 6 yearsThis is mixing absolute positions "getRawX" with relative positions "getRight". If you set a right or left margin on the editText you'll see how this breaks as the click is triggered on wrong coordinates.
-
Sotti over 6 yearsThis is mixing absolute positions "getRawX" with relative positions "getRight". If you set a right or left margin on the editText you'll see how this breaks as the click is triggered on wrong coordinates.
-
Sotti over 6 yearsThis is mixing absolute positions "getRawX" with relative positions "getRight". If you set a right or left margin on the editText you'll see how this breaks as the click is triggered on wrong coordinates.
-
Sotti over 6 yearsThis is mixing absolute positions "getRawX" with relative positions "getRight". If you set a right or left margin on the editText you'll see how this breaks as the click is triggered on wrong coordinates.
-
Sotti over 6 yearsThe problem with this approach is that falls apart as soon as you start changing the text size on the EditText. You might think that's just on the developer's side but it's not as far as the devices have text size in settings.You can avoid this using dp instead of sp on the EditText but it just makes things worse. The other problems are things like handling multiline EditTexts
-
Jevgenij Kononov over 6 yearsI have never used that for multi-line search, so sorry I never thought that this problem may appear. Probably blocking for multi line will help. Can you attach screenshot of app or view to see what happens? And I will try to resolved that and maybe help you (fix this code) and me for future use. Thanks.
-
Sotti over 6 yearsIt's very easy to replicate, it even happens on the layout preview as soon as you add 2 lines.
-
zohaib khaliq over 6 yearsi have added right margin on edit text, my code still works perfect
-
Vickie Kangare over 6 yearsMake return true otherwise action will not perform.
-
Max Makeichik almost 6 yearsI created an extension function for this case: ` @SuppressLint("ClickableViewAccessibility") inline fun TextView.onRightCompoundDrawableClick(crossinline f: () -> Unit) { this.setOnTouchListener(View.OnTouchListener { _, event -> val DRAWABLE_RIGHT = 2 if (event.action == MotionEvent.ACTION_UP) { if (event.rawX >= this.right - this.paddingRight - this.compoundDrawables[DRAWABLE_RIGHT].bounds.width()) { f() return@OnTouchListener true } } false }) } `
-
CoolMind almost 6 yearsA background for
EditText
should beandroid:background="@android:color/transparent"
. -
M. Reza Nasirloo over 5 yearsWhat about the relative drawable position, Start, and End?
-
Sevastyan Savanyuk over 5 years
View.getRight()
returns relative value. You should add position of the View to that to get it right. You get the absolute position of the view bygetLocationOnScreen(intArray)
and then getting thex
:intArray.get(0)
. -
methodsignature over 5 years"if you don't want to deal with the inconvenience of extending the class". Really wish we as programmer would work to extend our frameworks to our specific projects. If you need a component that acts like an EditText but supports compound drawable clicks, create one. Why expose how it works by externalizing the touch listener. Setting setOnTouchListener is not as clear as setOnRightIconClickListener.
-
farid_z over 4 yearsNeeds to subtract right padding, if any, for edit text when determining the start of the hit rectangle.
-
P Kuijpers over 4 yearsAs mentioned before, the location of the view is not considered (rawX instead of X), so it'll only work when the EditText is clipped to the parent. The answer/link from Paul Verest improves this, but doesn't take clickable padding into account. If you like to include this, incl. some explanation how it works, then check out my answer here: stackoverflow.com/a/58163977/2660216
-
Shyam Sunder over 3 yearsKotlin Extension's can be used here to make it look good & easy to use across the App.
fun EditText.setRightIconClick(clickEvent: () -> Unit){ setOnTouchListener(object : View.OnTouchListener{ override fun onTouch(v: View?, event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_UP) { if (event.rawX >= right - compoundDrawables[2].bounds.width() ) { clickEvent.invoke() return true } } return false } }) }
-
Khizar Hayat almost 3 yearsHats off Extension functions. thanks @mattia