EditText with delete button

ClearEditText

import android. content. Context;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.appcompat.widget.AppCompatEditText;

import com.blankj.utilcode.util.SizeUtils;

/**
 * <pre>
 * Inherit AppCompatEditText and implement TextWatcher and OnFocusChangeListener
 * Author: Caowj
 * Date: 2023/3/22 0022_10:14
 * 

*/
public class ClearEditText extends AppCompatEditText implements TextWatcher, View.OnFocusChangeListener {
private Drawable mClearDrawable;//clear button image
private boolean hasFocus;
private TextWatcher mTextWatcher;
private OnFocusChangeListener mOnFocusChangeListener;

/**
* Constructor routine operation, not too much explanation here
*/
public ClearEditText(Context context) {
this(context, null);
}

public ClearEditText(Context context, AttributeSet attrs) {
this(context, attrs, android. R. attr. editTextStyle);
}

public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init() {
hasFocus = hasFocus();
//Get the clear icon, which is set by drawableEnd or drawableRight in the layout file
//getCompoundDrawables: Returns drawables for the left, top, right, and bottom borders.
//getCompoundDrawablesRelative: Returns drawables for the start, top, end, and bottom borders.
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
mClearDrawable = getCompoundDrawablesRelative()[2];
}
if (mClearDrawable != null) {
//Set the position and size of the icon, getIntrinsicWidth() gets the displayed size instead of the size of the original picture
// mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
mClearDrawable.setBounds(0, 0, SizeUtils.dp2px(26), SizeUtils.dp2px(26));
}
//Default setting to hide the icon
setClearIconVisible(false);
//Set up the listener for focus changes
setOnFocusChangeListener(this);
//Set the listener for content changes in the input box
addTextChangedListener(this);
}

/**
* Simulate a click event by remembering where we pressed
*

* When we press the position at the width of the EditText – the distance from the right side of the text to the left edge of the icon – the distance from the left edge of the icon to the right edge of the control
*

* Even if the icon is clicked between the right edge of the EditText, the vertical direction is bounded by the height of the EditText
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP & amp; & amp; mClearDrawable != null) {
//getTotalPaddingRight() The distance from the left edge of the icon to the right edge of the control
//getCompoundDrawablePadding() indicates the distance from the right side of the text to the left edge of the icon
int left = getWidth() – getTotalPaddingRight() – getCompoundDrawablePadding();
boolean touchable = event.getX() > left & amp; & amp; event.getX() < getWidth(); if (touchable) { this.setText(""); } } return super.onTouchEvent(event); } /** * When the ClearEditText focus changes: *

* When there is focus and the input text content is not empty, the clear button will be displayed
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFocus = hasFocus;
setClearIconVisible(hasFocus & amp; & amp; !TextUtils.isEmpty(getText()));
if (mOnFocusChangeListener != null) {
mOnFocusChangeListener.onFocusChange(v, hasFocus);
}
}

/**
* When the content in the input box changes:
*

* When there is focus and the input text content is not empty, the clear button will be displayed
*/
@Override
public void onTextChanged(CharSequence s, int start, int count, int after) {
setClearIconVisible(hasFocus & amp; & amp; s. length() > 0);
if (mTextWatcher != null) {
mTextWatcher.onTextChanged(s, start, count, after);
}
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (mTextWatcher != null) {
mTextWatcher.beforeTextChanged(s, start, count, after);
}
}

@Override
public void afterTextChanged(Editable s) {
if (mTextWatcher != null) {
mTextWatcher.afterTextChanged(s);
}
}

/**
* Set the display and hiding of the clear icon, and call setCompoundDrawables to draw it for the EditText
*
* @param visible
*/
protected void setClearIconVisible(boolean visible) {
if (mClearDrawable == null) return;
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}

/**
* 1. If it is itself, call the implementation of the parent class,
*

* 2. If it is set externally, handle the callback by yourself
*/
@Override
public void setOnFocusChangeListener(OnFocusChangeListener l) {
if (l instanceof ClearEditText) {
super.setOnFocusChangeListener(l);
} else {
mOnFocusChangeListener = l;
}
}

@Override
public void addTextChangedListener(TextWatcher watcher) {
if (watcher instanceof ClearEditText) {
super.addTextChangedListener(watcher);
} else {
mTextWatcher = watcher;
}
}
}

use:

<com.test.widgets.ClearEditText
   android:id="@ + id/edit_sms_code"
    android:layout_width="wrap_content"
    android:layout_height="@dimen/dp_94"
    android:layout_marginLeft="@dimen/dp_80"
    android:background="@android:color/transparent"
    android:drawableEnd="@mipmap/ic_delete"
    android:hint="@string/edit_enter_sms_code_hint"
    android:imeOptions="actionDone"
    android:inputType="number"
    android:maxLength="6"
    android:text=""
    android:textColorHint="@color/gray_999"
    android:textSize="@dimen/sp_28" />