天天看点

自定义EditText—带有清除功能,在显示多行文本时清除按钮位于整个EditText的右下角

自定义带有清除功能的EditText不难,网上很多源码。简单来说,就是检测用户touch的位置,如果落在清除图标里面,则触发清除。这个清除图标是通过android:drawRight设置的。在EditText只有一行文本的时候,一切正常。可是如果EditText有多行文本时,清除图标就显示在中间(如下图)。

自定义EditText—带有清除功能,在显示多行文本时清除按钮位于整个EditText的右下角

显然,清除图标显示在右下角更加合理。我定义了一个EditText来实现这个效果。效果图如下。实现思路是,抛弃使用drawRight来显示清除图标。而是直接在onDraw函数中绘制清除图标。这么做是因为drawRight的位置不好控制,看了下TextView的onDraw函数,想要改变drawRight的绘制位置很难。要特别说明的是,我是通过android:drawRight来获得清除图标的,获得之后即把drawRight设为null了,这样可以不用自定义属性了。

自定义EditText—带有清除功能,在显示多行文本时清除按钮位于整个EditText的右下角

完整源码

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);
	}

}