为 EditText 的 Drawable 权限设置 onClickListener [重复]
Posted
技术标签:
【中文标题】为 EditText 的 Drawable 权限设置 onClickListener [重复]【英文标题】:Setting onClickListener for the Drawable right of an EditText [duplicate] 【发布时间】:2012-10-19 13:59:48 【问题描述】:在我的应用程序中,我有一个 EditText
,右侧有一个搜索图标。我使用了下面给出的代码。
<EditText
android:id="@+id/search"
android:layout_
android:layout_
android:layout_margin="4dip"
android:layout_weight="1"
android:background="@drawable/textfield_search1"
android:drawableLeft="@drawable/logo"
android:drawableRight="@drawable/search_icon"
android:hint="Search Anything..."
android:padding="4dip"
android:singleLine="true" />
我想为分配给右侧可绘制对象的搜索图标图像设置onClickListener
的EditText
。怎么可能?
【问题讨论】:
重复***.com/questions/3554377/… 使用 Android 提供的 API ***.com/a/26269435/185022 的最简单解决方案 :-) 这是最佳答案***.com/a/37032927/346309 【参考方案1】:简单的解决方案,使用 Android 已经提供的方法,而不是重新发明 wheeeeeeeeeel :-)
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;
);
【讨论】:
@user2273146 如果您的长度为 4,那么您的索引必须为 3。因为长度从 1 开始,所以没有 0 长度,但如果长度为 1,则索引为 0 为我工作。这是按下左图标的代码... if(event.getRawX() getRawX() 对我不起作用;所以我使用 getX() 并且它起作用了! 对我来说它适用于 (event.getRawX()+editComment.getPaddingLeft())ACTION_UP
不适合我。我改用ACTION_DOWN
【参考方案2】:
public class CustomEditText extends androidx.appcompat.widget.AppCompatEditText
private Drawable drawableRight;
private Drawable drawableLeft;
private Drawable drawableTop;
private Drawable drawableBottom;
int actionX, actionY;
private DrawableClickListener clickListener;
public CustomEditText (Context context, AttributeSet attrs)
super(context, attrs);
// this Contructure required when you are using this view in xml
public CustomEditText(Context context, AttributeSet attrs, int defStyle)
super(context, attrs, defStyle);
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
super.onSizeChanged(w, h, oldw, oldh);
@Override
public void setCompoundDrawables(Drawable left, Drawable top,
Drawable right, Drawable bottom)
if (left != null)
drawableLeft = left;
if (right != null)
drawableRight = right;
if (top != null)
drawableTop = top;
if (bottom != null)
drawableBottom = bottom;
super.setCompoundDrawables(left, top, right, bottom);
@Override
public boolean onTouchEvent(MotionEvent event)
Rect bounds;
if (event.getAction() == MotionEvent.ACTION_DOWN)
actionX = (int) event.getX();
actionY = (int) event.getY();
if (drawableBottom != null
&& drawableBottom.getBounds().contains(actionX, actionY))
clickListener.onClick(DrawablePosition.BOTTOM);
return super.onTouchEvent(event);
if (drawableTop != null
&& drawableTop.getBounds().contains(actionX, actionY))
clickListener.onClick(DrawablePosition.TOP);
return super.onTouchEvent(event);
// this works for left since container shares 0,0 origin with bounds
if (drawableLeft != null)
bounds = null;
bounds = drawableLeft.getBounds();
int x, y;
int extraTapArea = (int) (13 * getResources().getDisplayMetrics().density + 0.5);
x = actionX;
y = actionY;
if (!bounds.contains(actionX, actionY))
/** Gives the +20 area for tapping. */
x = (int) (actionX - extraTapArea);
y = (int) (actionY - extraTapArea);
if (x <= 0)
x = actionX;
if (y <= 0)
y = actionY;
/** Creates square from the smallest value */
if (x < y)
y = x;
if (bounds.contains(x, y) && clickListener != null)
clickListener
.onClick(DrawableClickListener.DrawablePosition.LEFT);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
if (drawableRight != null)
bounds = null;
bounds = drawableRight.getBounds();
int x, y;
int extraTapArea = 13;
/**
* IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE
* THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER
* CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE
* BOUND. - this process help to increase the tappable area of
* the rectangle.
*/
x = (int) (actionX + extraTapArea);
y = (int) (actionY - extraTapArea);
/**Since this is right drawable subtract the value of x from the width
* of view. so that width - tappedarea will result in x co-ordinate in drawable bound.
*/
x = getWidth() - x;
/*x can be negative if user taps at x co-ordinate just near the width.
* e.g views width = 300 and user taps 290. Then as per previous calculation
* 290 + 13 = 303. So subtract X from getWidth() will result in negative value.
* So to avoid this add the value previous added when x goes negative.
*/
if(x <= 0)
x += extraTapArea;
/* If result after calculating for extra tappable area is negative.
* assign the original value so that after subtracting
* extratapping area value doesn't go into negative value.
*/
if (y <= 0)
y = actionY;
/**If drawble bounds contains the x and y points then move ahead.*/
if (bounds.contains(x, y) && clickListener != null)
clickListener
.onClick(DrawableClickListener.DrawablePosition.RIGHT);
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
return super.onTouchEvent(event);
return super.onTouchEvent(event);
@Override
protected void finalize() throws Throwable
drawableRight = null;
drawableBottom = null;
drawableLeft = null;
drawableTop = null;
super.finalize();
public void setDrawableClickListener(DrawableClickListener listener)
this.clickListener = listener;
同时创建一个接口
public interface DrawableClickListener
public static enum DrawablePosition TOP, BOTTOM, LEFT, RIGHT ;
public void onClick(DrawablePosition target);
如果你需要任何帮助,请发表评论
还要在活动文件中的视图上设置drawableClickListener。
editText.setDrawableClickListener(new DrawableClickListener()
public void onClick(DrawablePosition target)
switch (target)
case LEFT:
//Do something here
break;
default:
break;
);
【讨论】:
我也会将 Edittext 作为参数传递给回调。但一个好的答案永远不会少。 我创建了自定义的 EditText。如果我触摸它去 onTouchMovement 方法的任何地方。但永远不会去这里“if (bounds.contains(x, y) && clickListener != null) clickListener .onClick(DrawableClickListener.DrawablePosition.RIGHT); event.setAction(MotionEvent.ACTION_CANCEL); return false; ”跨度> 嗨,我没有找到 CoreSystemContext.SCALE ,所以代码显示错误。我如何获得 CoreSystemContext.SCALE。请指教。 即可变保持器密度。使用 getResources().getDisplayMetrics().density 代替,您可能需要在其他文件中创建一个静态变量。这将 px 转换为 dp。一个简单的解决方案是删除该变量。 请在onTouchEvent(MotionEvent event)
方法中在if (event.getAction() == MotionEvent.ACTION_DOWN)
之后添加声明playSoundEffect(android.view.SoundEffectConstants.CLICK);
,以便用户获得点击声音。【参考方案3】:
这已经得到解答,但我尝试了一种不同的方法来使其更简单。
这个想法是使用在EditText
的右侧放置一个ImageButton
并为其设置负边距,以便EditText
流入ImageButton
,使其看起来像按钮在EditText
中。
<LinearLayout
android:layout_
android:layout_
android:orientation="horizontal">
<EditText
android:id="@+id/editText"
android:layout_weight="1"
android:layout_
android:layout_
android:hint="Enter Pin"
android:singleLine="true"
android:textSize="25sp"
android:paddingRight="60dp"
/>
<ImageButton
android:id="@+id/pastePin"
android:layout_marginLeft="-60dp"
style="?android:buttonBarButtonStyle"
android:paddingBottom="5dp"
android:src="@drawable/ic_action_paste"
android:layout_
android:layout_ />
</LinearLayout>
另外,如上所示,如果您不希望其中的文本在ImageButton
上飘过,您可以在EditText
中使用类似宽度的paddingRight
。
我在 android-studio 的布局设计器的帮助下猜测了边距大小,它在所有屏幕尺寸上看起来都相似。否则,您可以计算 ImageButton
的宽度并以编程方式设置边距。
【讨论】:
简单的东西效果最好。 这对于单个可绘制对象来说是多余的工作 各种设备都会出现边距和填充问题 Linter 会给你一个警告“低效的布局树,使用复合drawable”,代码也比drawableRight=""... 这种方法的问题是,一旦您开始更改 EditText 上的文本大小,它就会崩溃。您可能认为这只是在开发人员方面,但它并没有设备在设置中具有文本大小。您可以在 EditText 上使用 dp 而不是 sp 来避免这种情况,但这只会让事情变得更糟。其他问题是处理多行 EditTexts【参考方案4】:据我所知,您无法访问正确的图像,除非您覆盖 onTouch
事件。我建议使用RelativeLayout
,一个editText
和一个imageView
,并在图像视图上设置OnClickListener
,如下所示:
<RelativeLayout
android:id="@+id/rlSearch"
android:layout_
android:layout_
android:background="@android:drawable/edit_text"
android:padding="5dip" >
<EditText
android:id="@+id/txtSearch"
android:layout_
android:layout_
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/imgSearch"
android:background="#00000000"
android:ems="10"/>
<ImageView
android:id="@+id/imgSearch"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/btnsearch" />
</RelativeLayout>
【讨论】:
这种方法的问题是,一旦您开始更改 EditText 上的文本大小,它就会崩溃。您可能认为这只是在开发人员方面,但它并没有设备在设置中具有文本大小。您可以在 EditText 上使用 dp 而不是 sp 来避免这种情况,但这只会让事情变得更糟。其他问题是处理多行 EditTexts【参考方案5】:我知道这已经很老了,但我最近不得不做一些非常相似的事情,并想出了一个更简单的解决方案。
归结为以下步骤:
-
创建一个包含 EditText 和 Image 的 XML 布局
继承 FrameLayout 并扩展 XML 布局
为点击侦听器和任何其他您想要的行为添加代码...而不必担心点击的位置或任何其他杂乱的代码。
有关完整示例,请参阅此帖子: Handling click events on a drawable within an EditText
【讨论】:
【参考方案6】:请使用以下技巧:
使用您的图标创建一个图像按钮并将其背景颜色设置为透明。 把图片按钮放在EditText上 实现按钮的 'onclic'k 侦听器以执行您的功能【讨论】:
如果editText的大小增加了怎么办?如果我有很多需要这样做的editText怎么办,这通常会发生。 你需要明白这个问题!他/她不是在寻求替代解决方案。 这种方法的问题是,一旦您开始更改 EditText 上的文本大小,它就会崩溃。您可能认为这只是在开发人员方面,但它并没有设备在设置中具有文本大小。您可以在 EditText 上使用 dp 而不是 sp 来避免这种情况,但这只会让事情变得更糟。其他问题是处理多行 EditTexts以上是关于为 EditText 的 Drawable 权限设置 onClickListener [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Android Edittext Drawable 点击卡住焦点
笔画没有应用于矩形到xml drawable用作android中的edittext背景
解决android手机EditText设置光标颜色,android:textCursorDrawable="@drawable/corner_cursor" 华为手机无效果的问题