我已经在EditText小部件中添加了文本右侧的图像,使用以下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" />

但我想在单击嵌入图像时清除EditText。我该怎么做呢?


当前回答

分享我的处理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);
}

现在你可以处理任何触摸事件任何复合drawable的任何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);
}

同样,我们可以很容易地处理点击任何复合drawable的任何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;
                }
            }
        });

希望你和我一样喜欢。如果有任何变化,我会尽量在这里和相关的要点上保持更新。

其他回答

最好在编辑文本的右边有ImageButton,并给负布局边距与编辑文本重叠。在ImageButton上设置监听器并执行操作。

我是这样做的

            <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>

使用可扩展的textview缓冲区可能是一个解决方案。看看这个简短而切中要害的教程:首先,点击事件要容易得多

https://android-designing.blogspot.com/2017/01/spannable-textview-with-image-clickable.html?m=1

我创建了一个有用的抽象类DrawableClickListener实现OnTouchListener。

除了DrawableClickListener类之外,我还创建了4个额外的抽象类,它们扩展了DrawableClickListener类,并处理对正确象限的可绘制区域的单击。

LeftDrawableClickListener TopDrawableClickListener RightDrawableClickListener BottomDrawableClickListener


考虑要点

需要考虑的一件事是,如果这样做,图像不会调整大小;因此,在放入res/drawable文件夹之前,图像必须正确缩放。

如果你定义一个LinearLayout包含一个ImageView和一个TextView,这是很容易操纵图像的大小显示。


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 &quot;fuzz&quot; 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 &quot;fuzz&quot; 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 &quot;fuzz&quot; 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 &quot;fuzz&quot; 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 &quot;fuzz&quot; 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 &quot;fuzz&quot; 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;
        }

    }

}

这一切都很棒,但为什么不让它变得更简单呢?

不久前我也遇到过这种情况……和android touchlistener工作得很好,但在使用上有限制..我找到了另一个解决方案,我希望能帮助你:

    <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>