作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc。
书客创作
常常会在一些APP当中看到,当输入框输入内容之后,在输入框的右侧会显示一个清空的按钮,点击清空按钮,输入框的内容将会被清空。像这样的功能该如何实现呢?
今天就使用EditText的DrawableRight实现清空输入值功能。
应用场景
DrawableRight实现清空EditText输入框内容,是一个比较常见的功能,一般用于搜索框。
主要重难点
1、自定义EditText。通过继承EditText,在构造方法中实现DrawableRight初始化,以及设置View.OnFocusChangeListener, TextWatcher监听。
2、对DrawableRight的点击事件构造。EditText没有单独的一个实现DrawableRight点击事件,所以我们通过点击的位置判断DrawableRight是否被点击。即当按下的位置 在EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 与 EditText的宽度 - 图标到控件右边的间距之间,算点击了DrawableRight。
代码实现
在代码实现之前,首先要了解以下几个方法的含义:
drawable.setBounds(int, int, int, int);
该方法是Drawable类中的一个方法,表示设置图片边界,左上右下。
setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable);
该方法是设置EditText的Drawable,四个参数分别表示左上右下。
getCompoundDrawables()[i]
该方法是获取EditText的Drawable,获取的是一个数组,该数组有四个值,从0到3分别表示EditText左上右下的Drawable,没有的话则为null。
了解这几个方法之后,接下来分两步实现DrawableRight清空输入值功能。
1、自定义EditText
在cc.ibooker.ibooker目录下创建ClearEditText,让其继承EditText,并实现构造方法。
// 带清空功能的EditText-DrawableRight,监听焦点和输入值改变状态
public class ClearEditText extends android.support.v7.widget.AppCompatEditText implements View.OnFocusChangeListener, TextWatcher {
/**
* 删除Drawable引用
*/
private Drawable mClearDrawable;
/**
* 控件是否有焦点
*/
private boolean hasFocus;
// 构造方法 1->2->3
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() {
// Drawable顺序左上右下,0123
// 获取DrawRight内容
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
// 未设置默认DrawableRight
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mClearDrawable = getResources().getDrawable(R.mipmap.icon_clear, null);
} else {
mClearDrawable = getResources().getDrawable(R.mipmap.icon_clear);
}
}
// 设置Drawable大小和位置
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
// 添加焦点改变监听
setOnFocusChangeListener(this);
// 添加输入内容改变监听
addTextChangedListener(this);
}
// 焦点改变事件
// 当焦点在时,通过判断输入值,实现隐藏和现实DrawableRight
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFocus = hasFocus;
if (hasFocus) {
// 焦点存在,而且有输入值
setDrawableRightightVisible(getText().length() > 0);
} else {
// 焦点不存在时候,隐藏DrawableRight
setDrawableRightightVisible(false);
}
}
/**
* 隐藏或显示DrawableRight
*
* @param visible true=显示,false=隐藏
*/
private void setDrawableRightightVisible(boolean visible) {
// 控件setCompoundDrawables设置Drawable,隐藏则设置null,左上右下
Drawable drawableRight = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], drawableRight, getCompoundDrawables()[3]);
}
// 触摸事件-实现ClearDrawable清空功能
// 1、如何判断Drawable被点击?——通过判断点击的位置
// 2、什么时候实现清空?——当ClearDrawable不为空且被点击
@Override
public boolean onTouchEvent(MotionEvent event) {
// 判断手指是否触摸
if (event.getAction() == MotionEvent.ACTION_UP) {
// 判断ClearDrawable(DrawableRight)是否为空
if (getCompoundDrawables()[2] != null) {
// 当按下的位置 在EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 与 EditText的宽度 - 图标到控件右边的间距之间,算点击了图标,竖直方向不用考虑
// getTotalPaddingRight获取右侧图标以及右侧Padding和
// getPaddingRight获取右侧Padding值
boolean isTouchRight = event.getX() > (getWidth() - getTotalPaddingRight()) && (event.getX() < ((getWidth() - getPaddingRight())));
if (isTouchRight) {
this.setText("");
}
}
}
return super.onTouchEvent(event);
}
// 输入内容变化前
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (onTextChangedListener != null)
onTextChangedListener.beforeTextChanged(s, start, count, after);
}
// 输入内容变化时,判断是否有输入值=有 并且焦点=存在 则显示ClearDrawable
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
if (hasFocus) {
setDrawableRightightVisible(text.length() > 0);
}
if (onTextChangedListener != null)
onTextChangedListener.onTextChanged(text, start, lengthBefore, lengthAfter);
}
// 输入内容变化后
@Override
public void afterTextChanged(Editable s) {
if (onTextChangedListener != null)
onTextChangedListener.afterTextChanged(s);
}
// 文本改变接口监听
public interface OnTextChangedListener {
void beforeTextChanged(CharSequence s, int start, int count, int after);
void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter);
void afterTextChanged(Editable s);
}
private OnTextChangedListener onTextChangedListener;
public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
this.onTextChangedListener = onTextChangedListener;
}
}
2、在布局文件中引入自定义EditText
直接将自定义的ClearEditText,引入布局XML文件即可。
<cc.ibooker.ibooker.ClearEditText
android:id="@+id/ed_clear"
android:layout_width="match_parent"
android:layout_height="50dp"
android:drawableEnd="@mipmap/icon_clear"
android:drawableRight="@mipmap/icon_clear"
android:inputType="text"
android:padding="10dp" />
3、程序结构图
程序结构图微信公众号:书客创作
网友评论