Android EditText responds to click events such as drawable right

Posted by JH5 on Sat, 29 Jun 2019 00:53:27 +0200

Preface

In the input box EditText, we often add icons such as deleting X, drop-down arrows to get better user experience and needs. If on the right side, we often set the drawableRight attribute to achieve, then how do these icons respond to click events? Here's a brief record!

Method

First of all, we need to inherit AppCompat EditText and implement a custom EditText. (Now, in order to be compatible with and implement MD style, we will inherit AppCompat EditText instead of EditText. In addition, AS will give the corresponding error warning!)

Then, with the help of onTouchEvent, it responds to the click event of the icon according to the touch position, and judges whether the x and y coordinates of the finger are clicked on the drawable object. These parameters need to be clarified:

event.getRawX()//Relative to the absolute coordinates of the left boundary, the upper left corner is (0,0)
event.getX()//Relative to its own coordinates, the upper left corner of the space is (0,0)
getLeft()//Equivalent to margin, the distance between the left boundary of the control and its parent
getPaddingLeft()//Equivalent to padding, the distance between elements in a control and the control
getBounds().width()//Gets the width of the element drawing area
drawableRight.getIntrinsicWidth()//Get the actual width of drawable

Then you need to get this icon. Here you can get a drawable array of length 4 by calling getCompound Drawables (), and store drawableLeft, Right, Top, Bottom four image resource objects:

    final int DRAWABLE_LEFT = 0;
    final int DRAWABLE_TOP = 1;
    final int DRAWABLE_RIGHT = 2;
    final int DRAWABLE_BOTTOM = 3;

According to the location of the icon, you can get the corresponding picture Drawable.

Finally, by declaring an interface and defining a callback method, I will not go into details here, which is more common!

Specific realization

public class DropDownEditText extends AppCompatEditText {
    final int DRAWABLE_LEFT = 0;
    final int DRAWABLE_TOP = 1;
    final int DRAWABLE_RIGHT = 2;
    final int DRAWABLE_BOTTOM = 3;

    public DropDownEditText(Context context) {
        super(context);
    }

    public DropDownEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public interface OnDropArrowClickListener {
        void onDropArrowClick();
    }

    private OnDropArrowClickListener onDropArrowClickListener;

    public void setOnDropArrowClickListener(OnDropArrowClickListener onDropArrowClickListener) {
        this.onDropArrowClickListener = onDropArrowClickListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_UP) {
            Drawable drawableRight = getCompoundDrawables()[DRAWABLE_RIGHT];
            if (drawableRight != null) {
            //The x-axis coordinates of this click event, if > current control width - control right spacing - drawable actual display size
                if (event.getX() >= (getWidth() - getPaddingRight() - drawableRight.getIntrinsicWidth())) {
                    //Set up to click the EditText icon on the right to lose focus.
                    // Prevent clicking EditText icon on the right side of EditText to get focus and pop-up the soft keyboard
                    setFocusableInTouchMode(false);
                    setFocusable(false);
                    if (onDropArrowClickListener != null) {
                        onDropArrowClickListener.onDropArrowClick();
                    }
                } else {
                    setFocusableInTouchMode(true);
                    setFocusable(true);
                }
            }
        }
        return super.onTouchEvent(event);
    }
}

The example shows the icon on the right, in the same other position:
Right:

//Another direct approach
//Actually, it's the left-most drawable.xcoordinate,drawableRight.getIntrinsicWidth()==drawableRight.getBounds().width()Equal to the width of the icon
event.getRawX() >= (getRight() - drawableRight.getBounds().width())

On the left:

/**getX Relative to the x coordinate of the upper left corner of the control itself, <== the left margin of the control + the actual width of the image object. This getLeft is equivalent to margin, and getPadding Left is equivalent to padding.*/
event.getX() <= getLeft() + drawableLeft.getIntrinsicWidth()


event.getRawX() <= (getLeft() + drawableLeft.getBounds().width())

Above:

event.getY() <= getTop() + drawableTop.getIntrinsicHeight()

Below:

event.getX() > getHeight() - drawableBottom.getIntrinsicWidth()

call

Get the instance directly and call the method.

editText = (DropDownEditText) findViewById(R.id.xxxxx);
editText.setOnDropArrowClickListener(new DropDownEditText.OnDropArrowClickListener() {
    @Override
    public void onDropArrowClick() {
        //xxxxxxxx
    }
});

problem

When you click, you get the focus and pop up the soft keyboard. Here's a solution:
Android implements EditText to respond to drawable right click events
That is, if you click on the icon on the right, it will lose focus:

setFocusableInTouchMode(false);
setFocusable(false);

This method, although it can avoid pop-up input method, but EditText below the line, or will light up, the experience is not very good, if you know, you can guide, thank you!

Reference article:
EditText sets DrawableRight, DrawableLeft, DrawableTop... Click Events

Topics: Attribute Android