简介
EditText控件,对大家来说应该掌握的最基本的控件之一。一个app最开始的登录界面,帐号和密码输入框就是EditText控件,
平时输入帐号长长的一串,输入后发现错了,又要一个一个删,这时候如果有一个清除功能来清除所有就好了。下面我们就来自
定义这么一个带清除功能的编辑框控件。
思路
看到这个功能我的第一想法是EditText的不是有个drawableRight属性来添加有图标么,我们可以通过这个来添加清除按钮啊。
那么问题来了:
1、清除按钮什么时候显示?又什么时候隐藏呢?
2、清除按钮的清除事件怎么写呢,可不可以在编辑框的单击事件(OnClickListener)处理清除按钮的点击事件呢?
带着这两个问题,我们来开始进行编写
实现
第一个问题,清除按钮什么时候显示,什么时候隐藏?显而易见,当编辑框获得了焦点,且编辑框内容长度大于0的时候才需要
显示,没有内容或者编辑框都没获取焦点,还显示个毛是不!所以,理清了前面的思路和问题,我们很容易知道,可以继承
EditText控件来实现,又因为需要获取焦点且根据内容长度来判断是否显示清除按钮,我们还得实现
OnFocusChangeListener、TextWatcher监听,啥也不说了,上代码:
//EditText右侧的删除图标
private Drawable mClearDrawable;
//EditText是否聚焦
private boolean hasFocus;
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() {
mClearDrawable = getCompoundDrawables()[2];//获取有图标,0,1,2,3分别代表,左上右下
if (null == mClearDrawable) {
mClearDrawable = getResources().getDrawable(R.mipmap.clear);
}
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
//默认不显示clear图标
setClearIconVisible(false);
setOnFocusChangeListener(this);
addTextChangedListener(this);
}
/**
* 设置清除图标是否可见
* @param visible
*/
private void setClearIconVisible(boolean visible) {
Drawable right = (visible ? mClearDrawable : null);
setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1],
right, getCompoundDrawables()[3]);
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFocus = hasFocus;
if (hasFocus) {
setClearIconVisible(getText().length() > 0);//获取焦点且长度大于0时,清除图标显示
} else {
setClearIconVisible(false);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (hasFocus) {
setClearIconVisible(s.length() > 0);//长度改变时,依条件判断是否显示图标
}
}
如此则实现了符合条件的带清除按钮的编辑框,编辑框无内容时,清除图标不显示,有焦点且有内容时则显示。那如果实现点击
清除图标实现清除功能呢?现在我们来解决第二个问题,清除功能怎么实现?是否可以通过监听编辑框单击事件来实现呢?显
然,不符合要求,因为我们单击实现清除功能只针对清除图标区域,其他区域的单击不做清除处理,所以不能简单通过
OnClickListener来进行清除。那么,要如何实现呢?聪明如我们肯定就知道了,可以通过重写onTouchEvent事件,当
ACTION_UP动作时,看看当前触摸坐标是否在清除图标区域内,是则进行清除操作,否则不进行!ok,看代码:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()) {
if (null != getCompoundDrawables()[2]) {
int x = (int) event.getX();
int y = (int) event.getY();
Rect rect = getCompoundDrawables()[2].getBounds();
int height = rect.height();//清除图标高
int distance = (getHeight() - height) / 2;//清除图标顶部到控件顶部的距离
boolean w = (x < getWidth() - getPaddingRight()) && (x > getWidth() - getTotalPaddingRight());
boolean h = (y > distance) && (y < distance + height);
if (w && h) {
setText("");
}
}
}
return super.onTouchEvent(event);
}
好了,至此,带清除功能的编辑框控件,已完全实现,最后的展示效果如下