自定义带有清除功能的EditText不难,网上很多源码。简单来说,就是检测用户touch的位置,如果落在清除图标里面,则触发清除。这个清除图标是通过android:drawRight设置的。在EditText只有一行文本的时候,一切正常。可是如果EditText有多行文本时,清除图标就显示在中间(如下图)。
显然,清除图标显示在右下角更加合理。我定义了一个EditText来实现这个效果。效果图如下。实现思路是,抛弃使用drawRight来显示清除图标。而是直接在onDraw函数中绘制清除图标。这么做是因为drawRight的位置不好控制,看了下TextView的onDraw函数,想要改变drawRight的绘制位置很难。要特别说明的是,我是通过android:drawRight来获得清除图标的,获得之后即把drawRight设为null了,这样可以不用自定义属性了。
完整源码
package com.example.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.EditText;
public class EditTextWithClear extends EditText {
private Drawable drawableRight;
private boolean showClearIcon;
public EditTextWithClear(Context context) {
super(context);
}
public EditTextWithClear(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextWithClear(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
Drawable[] drawables = getCompoundDrawables();
// Store drawableRight
drawableRight = drawables[2];
setCompoundDrawablesWithIntrinsicBounds(drawables[0], drawables[1],
null, drawables[3]);
}
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if (0 == text.length()) {
showClearIcon = false;
} else {
showClearIcon = true;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP
&& showClearIcon
&& drawableRight != null
&& event.getX() >= (getWidth()
- drawableRight.getIntrinsicWidth() - getPaddingRight())
&& event.getY() >= (getHeight()
- drawableRight.getIntrinsicHeight() - getPaddingBottom())) {
setText("");
int cacheInputType = getInputType();
setInputType(InputType.TYPE_NULL);
super.onTouchEvent(event);
setInputType(cacheInputType);
return true;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
if (showClearIcon && drawableRight != null) {
float dy = getHeight() - drawableRight.getIntrinsicHeight()
- getPaddingBottom();
float dx = getWidth() - drawableRight.getIntrinsicWidth()
- getPaddingRight();
canvas.save();
canvas.translate(dx, dy);
drawableRight.draw(canvas);
canvas.restore();
}
super.onDraw(canvas);
}
}