我使用以下XML在EditText
小部件中添加了文本右侧的图像:
<EditText
android:id="@+id/txtsearch"
...
android:layout_gravity="center_vertical"
android:background="@layout/shape"
android:hint="Enter place,city,state"
android:drawableRight="@drawable/cross" />
但是我想在点击嵌入图片时清除EditText
。我怎么能这样做?
答案 0 :(得分:321)
实际上你不需要扩展任何类。假设我有一个带有drawableRight的EditText editComment
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;
}
});
我们getRawX()
因为我们希望在屏幕上获得触摸的实际位置,而不是相对于父级。
左键单击
if(event.getRawX() <= (editComment.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width()))
答案 1 :(得分:81)
非常非常好,感谢为此次讨论做出贡献的所有人。因此,如果您不想处理扩展课程的不便,您可以执行以下操作(仅针对正确的绘图实施)
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;
}
这是基于@Mark答案的裸骨监听器实现
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);
}
答案 2 :(得分:28)
请考虑以下事项。它不是最优雅的解决方案,但它可以工作,我只是测试了它。
创建自定义的EditText
班级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();
}
}
将布局XML更改为此(其中com.example
是您的实际项目包名称):
<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"
/>
最后,将此(或类似内容)添加到您的活动中:
…
CustomEditText et = (CustomEditText) this.findViewById(R.id.txtsearch);
…
对于嵌套drawable的触摸边界的计算,我可能有点偏僻,但你明白了。
我希望这会有所帮助。
答案 3 :(得分:20)
我创建了一个有用的抽象类 DrawableClickListener ,它实现了 OnTouchListener 。
除了 DrawableClickListener 类之外,我还创建了4个额外的抽象类,它们扩展了 DrawableClickListener 类,并处理了正确象限的可绘制区域的点击。 / p>
要考虑的事项
要考虑的一件事是,如果这样做,图像不会调整大小;因此,在放入 res / drawable 文件夹之前,图像必须正确缩放。
如果您定义包含 ImageView 和 TextView 的 LinearLayout ,则可以更轻松地操作所显示图像的大小。
<强> 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;
}
}
}
答案 4 :(得分:12)
最后一个贡献对contains(x,y)
的使用不会直接对getBounds()
的结果起作用(除非巧合,使用“左”drawables时)。 getBounds
方法仅提供使用原点0,0标准化的可绘制项目的Rect
定义点 - 因此,您实际上需要对原始帖子进行数学运算以确定点击是否在包含EditText维度的上下文中drawable的区域,但是将其更改为top,right,left等。或者,您可以描述Rect
实际上相对于其在EditText
中的位置的坐标容器和使用contains()
,虽然最后你正在做相同的数学运算。
将它们组合起来为您提供了一个非常完整的解决方案,我只添加了一个实例属性consumesEvent
,让API用户可以通过使用其结果设置{{1}来决定是否应该传递click事件或不。
此外,我无法理解为什么ACTION_CANCEL
和bounds
,actionX
值是实例属性而不仅仅是堆栈上的本地属性。
这是基于上面的实现的剪切,我把它放在一起。它修复了一个问题,即正确使用您需要返回false的事件。它增加了一个“模糊”因素。在我actionY
字段中的语音控件图标的用例中,我发现很难点击,因此模糊增加了被视为单击可绘制的有效边界。对我来说EditText
效果很好。我只需要15
所以我没有把数学插入其他人,以节省一些空间,但你看到了这个想法。
drawableRight
答案 5 :(得分:11)
非常简单。 假设你在EditText'txtsearch'的左侧有一个drawable。 以下将做到这一点。
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语句更改为:
if(event.getRawX() >= txtsearch.getRight() - txtsearch.getTotalPaddingRight())
同样,你可以为所有复合绘图做到这一点。
txtsearch.getTotalPaddingTop()
txtsearch.getTotalPaddingBottom()
此方法调用返回该侧的所有填充,包括任何drawable。您甚至可以将它用于TextView,Button等。
点击here以获取Android开发者网站的参考。
答案 6 :(得分:7)
扩展了RyanM的想法我创建了一个更灵活的版本,它支持所有可绘制的类型(顶部,底部,左侧,右侧)。虽然下面的代码扩展了TextView,但是将它改编为EditText只是用“extends EditText”交换“extends TextView”的情况。从XML实例化小部件与RyanM的示例相同,禁止小部件名称。
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
import com.example.DrawableClickListener.DrawablePosition;
public class ButtonTextView extends TextView {
private Drawable drawableRight;
private Drawable drawableLeft;
private Drawable drawableTop;
private Drawable drawableBottom;
private int actionX, actionY;
private DrawableClickListener clickListener;
public ButtonTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ButtonTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonTextView(Context context) {
super(context);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
if (right != null) {
drawableRight = right;
}
if (left != null) {
drawableLeft = left;
}
if (top != null) {
drawableTop = top;
}
if (bottom != null) {
drawableBottom = bottom;
}
super.setCompoundDrawables(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
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);
}
if (drawableLeft != null && drawableLeft.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.LEFT);
return super.onTouchEvent(event);
}
if (drawableRight != null && drawableRight.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.RIGHT);
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;
}}
DrawableClickListener就像这样简单:
public interface DrawableClickListener {
public static enum DrawablePosition { TOP, BOTTOM, LEFT, RIGHT };
public void onClick(DrawablePosition target); }
然后是实际的实施:
class example implements DrawableClickListener {
public void onClick(DrawablePosition target) {
switch (target) {
case LEFT:
doSomethingA();
break;
case RIGHT:
doSomethingB();
break;
case BOTTOM:
doSomethingC();
break;
case TOP:
doSomethingD();
break;
default:
break;
}
}}
p.s。:如果你没有设置监听器,触摸TextView将导致NullPointerException。您可能希望在代码中添加更多偏执狂。
答案 7 :(得分:6)
我已经在科特林实施
edPassword.setOnTouchListener { _, event ->
val DRAWABLE_RIGHT = 2
val DRAWABLE_LEFT = 0
val DRAWABLE_TOP = 1
val DRAWABLE_BOTTOM = 3
if (event.action == MotionEvent.ACTION_UP) {
if (event.rawX >= (edPassword.right - edPassword.compoundDrawables[DRAWABLE_RIGHT].bounds.width())) {
edPassword.setText("")
true
}
}
false
}
答案 8 :(得分:6)
它为我工作,
SonarClient client = SonarClient.builder()
.url(url)
.login(login)
.password(password)
.build();
答案 9 :(得分:3)
只需复制粘贴以下代码即可。
editMsg.setOnTouchListener(new View.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() >= (editMsg.getRight() - editMsg.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
Toast.makeText(ChatActivity.this, "Message Sent", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
});
答案 10 :(得分:3)
如果drawable在左边,这将对你有所帮助。 (对于那些使用RTL布局的人)
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() <= (searchbox.getLeft() + searchbox.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) {
// your action here
return true;
}
}
return false;
}
});
答案 11 :(得分:3)
我知道这已经很老了,但我最近不得不做类似的事情......在看到这是多么困难之后,我提出了一个更简单的解决方案:
就我而言,我需要一个能够用按钮清除文本的EditText。我希望它看起来像SearchView,但由于种种原因,我并不想使用该类。以下示例显示了我是如何完成此任务的。即使它与焦点更改没有关系,但原则是相同的,我认为发布实际工作代码比组合一个可能无法完全按照我预期工作的示例更有益:
这是我的布局:clearable_edit_text.xml
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/edit_text_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- NOTE: Visibility cannot be set to "gone" or the padding won't get set properly in code -->
<ImageButton
android:id="@+id/edit_text_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center_vertical"
android:background="@drawable/ic_cancel_x"
android:visibility="invisible"/>
</merge>
这是膨胀该布局的类:ClearableEditText.java
public class ClearableEditText extends FrameLayout {
private boolean mPaddingSet = false;
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
*/
public ClearableEditText (final Context context) {
this(context, null, 0);
}
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
* @param attrs The attribute set used to customize this instance
*/
public ClearableEditText (final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
* @param attrs The attribute set used to customize this instance
* @param defStyle The default style to be applied to this instance
*/
public ClearableEditText (final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
final LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.clearable_edit_text, this, true);
}
@Override
protected void onFinishInflate () {
super.onFinishInflate();
final EditText editField = (EditText) findViewById(R.id.edit_text_field);
final ImageButton clearButton = (ImageButton) findViewById(R.id.edit_text_clear);
//Set text listener so we can show/hide the close button based on whether or not it has text
editField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged (final CharSequence charSequence, final int i, final int i2, final int i3) {
//Do nothing here
}
@Override
public void onTextChanged (final CharSequence charSequence, final int i, final int i2, final int i3) {
//Do nothing here
}
@Override
public void afterTextChanged (final Editable editable) {
clearButton.setVisibility(editable.length() > 0 ? View.VISIBLE : View.INVISIBLE);
}
});
//Set the click listener for the button to clear the text. The act of clearing the text will hide this button because of the
//text listener
clearButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick (final View view) {
editField.setText("");
}
});
}
@Override
protected void onLayout (final boolean changed, final int left, final int top, final int right, final int bottom) {
super.onLayout(changed, left, top, right, bottom);
//Set padding here in the code so the text doesn't run into the close button. This could be done in the XML layout, but then if
//the size of the image changes then we constantly need to tweak the padding when the image changes. This way it happens automatically
if (!mPaddingSet) {
final EditText editField = (EditText) findViewById(R.id.edit_text_field);
final ImageButton clearButton = (ImageButton) findViewById(R.id.edit_text_clear);
editField.setPadding(editField.getPaddingLeft(), editField.getPaddingTop(), clearButton.getWidth(), editField.getPaddingBottom());
mPaddingSet = true;
}
}
}
为了使这个答案更符合问题,应采取以下步骤:
答案 12 :(得分:2)
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp" >
<EditText
android:id="@+id/edt_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@drawable/txt_box_blank"
android:ems="10"
android:hint="@string/statusnote"
android:paddingLeft="5dp"
android:paddingRight="10dp"
android:textColor="@android:color/black" />
<Button
android:id="@+id/note_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="1dp"
android:layout_marginTop="5dp"
android:background="@android:drawable/ic_delete" />
</FrameLayout>
答案 13 :(得分:1)
txt.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
if (event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() <= (txt
.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width() +
txt.getPaddingLeft() +
txt.getLeft())) {
//TODO do code here
}
return true;
}
}
return false;
}
});
答案 14 :(得分:1)
这一切都很棒,但为什么不让它变得非常简单呢?
我已经面对那也不久前...而且android touchlistiner工作得很好但是在使用方面有限制......我来到了另一个解决方案,我希望这会对你有所帮助:
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/zero_row">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/loadingProgressBar"
android:layout_gravity="center"
android:layout_width="28dp"
android:layout_height="28dp" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:background="@drawable/edittext_round_corners"
android:layout_height="match_parent"
android:layout_marginLeft="5dp">
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
app:srcCompat="@android:drawable/ic_menu_search"
android:id="@+id/imageView2"
android:layout_weight="0.15"
android:layout_gravity="center|right"
android:onClick="OnDatabaseSearchEvent" />
<EditText
android:minHeight="40dp"
android:layout_marginLeft="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/edittext_round_corners"
android:inputType="textPersonName"
android:hint="Search.."
android:textColorHint="@color/AndroidWhite"
android:textColor="@color/AndroidWhite"
android:ems="10"
android:id="@+id/e_d_search"
android:textCursorDrawable="@color/AndroidWhite"
android:layout_weight="1" />
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
app:srcCompat="@drawable/ic_oculi_remove2"
android:id="@+id/imageView3"
android:layout_gravity="center|left"
android:layout_weight="0.15"
android:onClick="onSearchEditTextCancel" />
</LinearLayout>
<!--android:drawableLeft="@android:drawable/ic_menu_search"-->
<!--android:drawableRight="@drawable/ic_oculi_remove2"-->
</LinearLayout>
</LinearLayout>
现在,您可以创建ImageClick侦听器或事件,并使用文本执行任何操作。这个edittext_round_corners.xml文件
<item android:state_pressed="false" android:state_focused="false">
<shape>
<gradient
android:centerY="0.2"
android:startColor="@color/colorAccent"
android:centerColor="@color/colorAccent"
android:endColor="@color/colorAccent"
android:angle="270"
/>
<stroke
android:width="0.7dp"
android:color="@color/colorAccent" />
<corners
android:radius="5dp" />
</shape>
</item>
答案 15 :(得分:1)
复合绘图不应该是可点击的。 在水平LinearLayout中使用单独的视图并在它们上使用单击处理程序更清晰。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:background="@color/white"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_marginRight="20dp"
android:layout_marginEnd="20dp"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:translationZ="4dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/white"
android:minWidth="40dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_search_map"/>
<android.support.design.widget.TextInputEditText
android:id="@+id/search_edit"
style="@style/EditText.Registration.Map"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="@string/hint_location_search"
android:imeOptions="actionSearch"
android:inputType="textPostalAddress"
android:maxLines="1"
android:minHeight="40dp" />
<ImageView
android:id="@+id/location_gps_refresh"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/white"
android:minWidth="40dp"
android:scaleType="center"
app:srcCompat="@drawable/selector_ic_gps"/>
</LinearLayout>
答案 16 :(得分:1)
@Override
public boolean onTouch(View v, MotionEvent event) {
Drawable drawableObj = getResources().getDrawable(R.drawable.search_btn);
int drawableWidth = drawableObj.getIntrinsicWidth();
int x = (int) event.getX();
int y = (int) event.getY();
if (event != null && event.getAction() == MotionEvent.ACTION_UP) {
if (x >= (searchPanel_search.getWidth() - drawableWidth - searchPanel_search.getPaddingRight())
&& x <= (searchPanel_search.getWidth() - searchPanel_search.getPaddingRight())
&& y >= searchPanel_search.getPaddingTop() && y <= (searchPanel_search.getHeight() - searchPanel_search.getPaddingBottom())) {
getSearchData();
}
else {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchPanel_search, InputMethodManager.SHOW_FORCED);
}
}
return super.onTouchEvent(event);
}
答案 17 :(得分:1)
最好将ImageButton置于编辑文本的右侧,并使负布局边距与编辑文本重叠。在ImageButton上设置监听器并执行操作。
答案 18 :(得分:1)
对于任何不想实施怪异点击处理的人。您可以使用RelativeLayout
实现相同的目标。有了它,您甚至可以自由处理可绘制的定位。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.TextInputLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:src="@drawable/ic_undo"/>
</RelativeLayout>
ImageView
位置与您使用drawableEnd
的位置相同 - 此外,您不需要所有触控侦听器处理。只需点击ImageView
的点击监听器就可以了。
答案 19 :(得分:1)
这对我有用:)也许这对你有帮助
edit_account_name.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (event.getRawX() >= (edit_account_name.getRight())) {
//clicked
return true;
}
}
return false;
}
});
答案 20 :(得分:1)
按照以下代码进行右侧,左侧,上侧,下方点击:
edittextview_confirmpassword.setOnTouchListener(new View.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() >= (edittextview_confirmpassword.getRight() - edittextview_confirmpassword.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here edittextview_confirmpassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
return true;
}
}else{
edittextview_confirmpassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
return false;
}
});
}
答案 21 :(得分:1)
以前的解决方案都无法在 Xamarin Android 中使用。我可以使用以下方法来使正确的可绘制点击侦听器正常工作:
创建以下del w2v.wv.vectors_norm
事件监听器:
OnEditTextTouch
订阅触摸事件:
private void OnEditTextTouch(object sender, View.TouchEventArgs e)
{
var rightDrawable = _autoCompleteTextViewSearch.GetCompoundDrawables()[2];
if (rightDrawable == null || e.Event.Action != MotionEventActions.Up)
{
e.Handled = false;
return;
}
if (e.Event.GetX() >= _autoCompleteTextViewSearch.Width - _autoCompleteTextViewSearch.TotalPaddingRight)
{
// Invoke your desired action here.
e.Handled = true;
}
// Forward the event along to the sender (crucial for default behaviour)
(sender as AutoCompleteTextView)?.OnTouchEvent(e.Event);
}
答案 22 :(得分:0)
我做了这样的事情
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:id="@+id/til_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textColorHint="@color/colorSilver">
<android.support.design.widget.TextInputEditText
android:id="@+id/tiet_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|left"
android:hint="@string/rep_hint"
android:inputType="textMultiLine"
android:maxLines="3"
android:drawableEnd="@drawable/ic_attach_photo"
android:drawablePadding="5dp"
android:textColor="@color/colorPrimaryText"
android:textColorHint="@color/colorSilver"
/>
</android.support.design.widget.TextInputLayout>
<View
android:id="@+id/right_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="12dp"
android:background="@color/clear" />
</RelativeLayout>
答案 23 :(得分:0)
这是我的简单解决方案,只需将ImageButton
放在EditText
上:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText android:id="@+id/editTextName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:imeOptions="actionSearch"
android:inputType="text"/>
<ImageButton android:id="@+id/imageViewSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_action_search"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
答案 24 :(得分:0)
科特林是一门很棒的语言,每个类都可以使用新方法进行扩展。让我们为EditText类引入一种新方法,该方法将捕获点击到正确可绘制对象的位置。
fun EditText.onRightDrawableClicked(onClicked: (view: EditText) -> Unit) {
this.setOnTouchListener { v, event ->
var hasConsumed = false
if (v is EditText) {
if (event.x >= v.width - v.totalPaddingRight) {
if (event.action == MotionEvent.ACTION_UP) {
onClicked(this)
}
hasConsumed = true
}
}
hasConsumed
}
}
您可以看到它将回调函数作为参数,当用户单击右侧可绘制对象时会调用该函数。
val username = findViewById<EditText>(R.id.username_text)
username.onRightDrawableClicked {
it.text.clear()
}
答案 25 :(得分:0)
使用可扩展的textview缓冲区可能是一种解决方案。看一下这个简短的要点教程:对于其中一个,单击事件要容易得多
https://android-designing.blogspot.com/2017/01/spannable-textview-with-image-clickable.html?m=1
答案 26 :(得分:0)
Hardik4560建议,我猜这是一个好方法,
答案 27 :(得分:0)
//单击右键图标
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_RIGHT = 2;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (createEventBinding.etAddressLine1.getRight() - createEventBinding.etAddressLine1.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
Toast.makeText(getActivity(), "Right icon click", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
});
答案 28 :(得分:0)
我已经采用@AZ_的解决方案并将其转换为kotlin扩展函数:
因此将其复制到您的代码中:
@SuppressLint("ClickableViewAccessibility")
fun EditText.setDrawableRightTouch(setClickListener: () -> Unit) {
this.setOnTouchListener(View.OnTouchListener { _, event ->
val DRAWABLE_LEFT = 0
val DRAWABLE_TOP = 1
val DRAWABLE_RIGHT = 2
val DRAWABLE_BOTTOM = 3
if (event.action == MotionEvent.ACTION_UP) {
if (event.rawX >= this.right - this.compoundDrawables[DRAWABLE_RIGHT].bounds.width()
) {
setClickListener()
return@OnTouchListener true
}
}
false
})
}
您可以仅在setDrawableRightTouch
上调用EditText
函数来使用它:
yourEditText.setDrawableRightTouch {
//your code
}
答案 29 :(得分:0)
上述问题的一个可能解决方案是使用 android 的新材料组件 TextInputLayout。
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/searchInput"
style="@style/Widget.App.TextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search"
app:endIconMode="custom"
app:endIconContentDescription="Search"
app:endIconDrawable="@drawable/ic_search">
<EditText
android:id="@+id/et_search"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.google.android.material.textfield.TextInputLayout>
此处的 TextInputLayout 属性 endIconMode 设置后,会在封闭的 EditText 的末尾放置一个按钮。
另外 app:endIconMode = "custom"
允许自定义图标的点击功能
最后聆听结束图标点击调用封闭 TextInputLayout 组件上的 setEndIconClickListener()。
答案 30 :(得分:0)
我提供了一个简短的解决方案,该解决方案甚至适用于对话的片段。
//The listener of a drawableEnd button for clear a TextInputEditText
textValue.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
final TextView textView = (TextView)v;
if(event.getX() >= textView.getWidth() - textView.getCompoundPaddingEnd()) {
textView.setText(""); //Clear a view, example: EditText or TextView
return true;
}
}
return false;
}
});
答案 31 :(得分:0)
这么多解决方案,但是当我连续有两个字段时,没有一个对我有用。 这是添加清除按钮以编辑文本的解决方案,这在我有两个字段或一个字段连续的情况下对我有用。用科特林写的!
@SuppressLint("PrivateResource")
fun <T : EditText> T.withClear(): T {
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable) {
setCompoundDrawablesWithIntrinsicBounds(0, 0,
if (editable.isNotEmpty()) abc_ic_clear_material else 0, 0)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
})
setOnTouchListener { _, event ->
if (event.action == ACTION_UP && event.x >= (right - this.compoundPaddingRight)) {
setText("")
return@setOnTouchListener true
}
false
}
return this
}
答案 32 :(得分:0)
以上解决方案有效,但有副作用。如果您有一个EditText带有正确的可绘制对象,例如
在图形对象上单击一下,您将获得一个PASTE按钮。参见How to disable paste in onClickListener for the Drawable right of an EditText Android (inside icon EditText)。
答案 33 :(得分:0)
我已经看过几个解决方案,但我并不相信任何一个解决方案。要么非常复杂,要么太简单(不可重复使用)。
这是我最喜欢的方法:
mEditText.setOnTouchListener(
new OnEditTextRightDrawableTouchListener(mEditText) {
@Override
public void OnDrawableClick() {
// The right drawable was clicked. Your action goes here.
}
});
这是可重复使用的触控听众:
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.EditText;
public abstract class OnEditTextRightDrawableTouchListener implements OnTouchListener {
private final EditText mEditText;
public OnEditTextRightDrawableTouchListener(@NonNull final EditText editText) {
mEditText = editText;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
final int DRAWABLE_RIGHT_POSITION = 2;
final Drawable drawable = mEditText.getCompoundDrawables()[DRAWABLE_RIGHT_POSITION];
if (drawable != null) {
final float touchEventX = motionEvent.getX();
final int touchAreaRight = mEditText.getRight();
final int touchAreaLeft = touchAreaRight - drawable.getBounds().width();
if (touchEventX >= touchAreaLeft && touchEventX <= touchAreaRight) {
view.performClick();
OnDrawableClick();
}
return true;
}
}
return false;
}
public abstract void OnDrawableClick();
}
答案 34 :(得分:0)
我创建了一个简单的自定义触摸侦听器类而不是自定义的EditText
public class MyTouchListener implements View.OnTouchListener {
private EditText editText;
public MyTouchListener(EditText editText) {
this.editText = editText;
setupDrawable(this.editText);
}
private void setupDrawable(final EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length()>0)
editText.setCompoundDrawablesWithIntrinsicBounds(0,0, R.drawable.clearicon,0);
else
editText.setCompoundDrawablesWithIntrinsicBounds(0,0, 0,0);
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(editText.getCompoundDrawables()[2]!=null){
if(event.getX() >= (editText.getRight()- editText.getLeft() - editText.getCompoundDrawables()[2].getBounds().width())) {
editText.setText("");
}
}
}
return false;
}
}
当EditText为空时,将无法绘制。当我们开始编辑以清除EditText时,将显示一个drawable。
您可以设置触控侦听器
mEditText.setOnTouchListener(new MyTouchListener(mEditText));
答案 35 :(得分:0)
分享我处理TextView复合可绘制点击和触摸事件的通用解决方案。
首先我们需要一个触摸事件处理程序:
/**
* Handles compound drawable touch events.
* Will intercept every event that happened inside (calculated) compound drawable bounds, extended by fuzz.
* @see TextView#getCompoundDrawables()
* @see TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)
*/
public abstract class CompoundDrawableTouchListener implements View.OnTouchListener {
private final String LOG_TAG = "CmpDrawableTouch";
private final int fuzz;
public static final int LEFT = 0;
public static final int TOP = 1;
public static final int RIGHT = 2;
public static final int BOTTOM = 3;
private static final int[] DRAWABLE_INDEXES = {LEFT, TOP, RIGHT, BOTTOM};
/**
* Default constructor
*/
public CompoundDrawableTouchListener() {
this(0);
}
/**
* Constructor with fuzz
* @param fuzz desired fuzz in px
*/
public CompoundDrawableTouchListener(int fuzz) {
this.fuzz = fuzz;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!(view instanceof TextView)) {
Log.e(LOG_TAG, "attached view is not instance of TextView");
return false;
}
TextView textView = (TextView) view;
Drawable[] drawables = textView.getCompoundDrawables();
int x = (int) event.getX();
int y = (int) event.getY();
for (int i : DRAWABLE_INDEXES) {
if (drawables[i] == null) continue;
Rect bounds = getRelativeBounds(i, drawables[i], textView);
Rect fuzzedBounds = addFuzz(bounds);
if (fuzzedBounds.contains(x, y)) {
MotionEvent relativeEvent = MotionEvent.obtain(
event.getDownTime(),
event.getEventTime(),
event.getAction(),
event.getX() - bounds.left,
event.getY() - bounds.top,
event.getMetaState());
return onDrawableTouch(view, i, bounds, relativeEvent);
}
}
return false;
}
/**
* Calculates compound drawable bounds relative to wrapping view
* @param index compound drawable index
* @param drawable the drawable
* @param view wrapping view
* @return {@link Rect} with relative bounds
*/
private Rect getRelativeBounds(int index, @NonNull Drawable drawable, View view) {
Rect drawableBounds = drawable.getBounds();
Rect bounds = new Rect();
switch (index) {
case LEFT:
bounds.offsetTo(view.getPaddingLeft(),
view.getHeight() / 2 - bounds.height() / 2);
break;
case TOP:
bounds.offsetTo(view.getWidth() / 2 - bounds.width() / 2,
view.getPaddingTop());
break;
case RIGHT:
bounds.offsetTo(view.getWidth() - view.getPaddingRight() - bounds.width(),
view.getHeight() / 2 - bounds.height() / 2);
break;
case BOTTOM:
bounds.offsetTo(view.getWidth() / 2 - bounds.width() / 2,
view.getHeight() - view.getPaddingBottom() - bounds.height());
break;
}
return bounds;
}
/**
* Expands {@link Rect} by given value in every direction relative to its center
* @param source given {@link Rect}
* @return result {@link Rect}
*/
private Rect addFuzz(Rect source) {
Rect result = new Rect();
result.left = source.left - fuzz;
result.right = source.right + fuzz;
result.top = source.top - fuzz;
result.bottom = source.bottom + fuzz;
return result;
}
/**
* Compound drawable touch-event handler
* @param v wrapping view
* @param drawableIndex index of compound drawable which recicved the event
* @param drawableBounds {@link Rect} with compound drawable bounds relative to wrapping view.
* Fuzz not included
* @param event event with coordinated relative to wrapping view - i.e. within {@code drawableBounds}.
* If using fuzz, may return negative coordinates.
*/
protected abstract boolean onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event);
}
现在,您可以通过以下方式处理任何TextView的任何复合体上的任何触摸事件:
textView1.setOnTouchListener(new CompoundDrawableTouchListener() {
@Override
protected void onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event) {
switch(v.getId()) {
case R.id.textView1:
switch(drawableIndex) {
case CompoundDrawableTouchListener.RIGHT:
doStuff();
break;
}
break;
}
}
});
只对点击感兴趣?只需通过MotionEvent操作过滤掉:
/**
* Handles compound drawable click events.
* @see TextView#getCompoundDrawables()
* @see TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)
* @see CompoundDrawableTouchListener
*/
public abstract class CompoundDrawableClickListener extends CompoundDrawableTouchListener {
/**
* Default constructor
*/
public CompoundDrawableClickListener() {
super();
}
/**
* Constructor with fuzz
* @param fuzz desired fuzz in px
*/
public CompoundDrawableClickListener(int fuzz) {
super(fuzz);
}
@Override
protected void onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) onDrawableClick(v, drawableIndex);
return true;
}
/**
* Compound drawable touch-event handler
* @param v wrapping view
* @param drawableIndex index of compound drawable which recicved the event
*/
protected abstract void onDrawableClick(View v, int drawableIndex);
}
我们可以轻松处理任何TextView的任何复合可绘制点击:
textView1.setOnTouchListener(new CompoundDrawableClickListener() {
@Override
protected void onDrawableClick(View v, int drawableIndex) {
switch(v.getId()) {
case R.id.textView1:
switch(drawableIndex) {
case CompoundDrawableTouchListener.RIGHT:
doStuff();
break;
}
break;
}
}
});
希望你像我一样喜欢它。如果有任何变化,我会尽量在related gist更新。
答案 36 :(得分:0)
我在Mono.Droid(Xamarin)中实现了@aristo_sh答案,因为它是一个匿名的代理方法,你不能返回true或false,你必须采取e.Event.Handled。我也在点击
隐藏键盘<authentication mode="Windows" />
<identity impersonate="true" />
答案 37 :(得分:0)
我想建议一种可绘制左派的方法! 我尝试了这段代码并且有效。
txtsearch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
int start=txtsearch.getSelectionStart();
int end=txtsearch.getSelectionEnd();
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() <= (txtsearch.getLeft() + txtsearch.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) {
//Do your action here
return true;
}
}
return false;
}
});
}
答案 38 :(得分:-1)
final TextView mTvTitle = (TextView)findViewById(R.id.tvTitle1);
mTvTitle.setOnTouchListener(new View.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() <= (mTvTitle.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) {
// your action here
Intent intent = new Intent(DeAddExpences.this,DeHomeActivity.class);
startActivity(intent);
return true;
}
}
return true;
}
});