自定義帶有清除功能的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);
}
}