自定义View之带删除按钮的编辑框

前言

什么都不说了,先上效果图

带删除功能的编辑框

代码

主要是使用了getCompoundDrawables()方法设置删除图片,返回数据是一个数组,分别对应如下位置的4张图片:左、上、右、下。

xml中对应的设置是

左:android:drawableLeft

上:android:drawableTop

右:android:drawableRight

下:android:drawableBottom

我这边将删除图片放在了右边,所以使用getCompoundDrawables()[2]

配合setOnFocusChangeListener()addTextChangedListener()onTouchEvent()实现删除图标的显示与隐藏。

完整代码如下,代码中写了详细的注释,这里就不再啰嗦了。

使用的图片下载:删除按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* <pre>
* author : Haitao
* blog : http://www.nhtzj.com
* time : 2017/6/22
* desc : 带删除按钮的编辑框
* version: 1.0
* </pre>
*/
public class ClearEditText extends AppCompatEditText implements View.OnFocusChangeListener,
TextWatcher {
//EditText右侧的删除按钮
private Drawable mClearDrawable;
private boolean hasFoucs;

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 defStyle) {
super(context, attrs, defStyle);
init();
}

private void init() {
// 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片,获取图片的顺序是左上右下(0,1,2,3,)
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
mClearDrawable = getResources().getDrawable(
R.drawable.edit_delete);
}

// mClearDrawable.setBounds(0, 0, DeviceUtils.dp2px(getContext(), 20), DeviceUtils.dp2px(getContext(), 20));
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
// 默认设置隐藏图标
setClearIconVisible(false);
// 设置焦点改变的监听
setOnFocusChangeListener(this);
// 设置输入框里面内容发生改变的监听
addTextChangedListener(this);
}

/*
*给删除图标设置点击处理
*
*@说明:isInnerWidth, isInnerHeight为ture,触摸点在删除图标之内,则视为点击了删除图标
* event.getX() 获取相对应自身左上角的X坐标
* event.getY() 获取相对应自身左上角的Y坐标
* getWidth() 获取控件的宽度
* getHeight() 获取控件的高度
* getTotalPaddingRight() 获取删除图标左边缘到控件右边缘的距离
* getPaddingRight() 获取删除图标右边缘到控件右边缘的距离
*
* isInnerWidth:点击处x坐标是否在删除图标上
* getWidth() - getTotalPaddingRight() 计算删除图标左边缘到控件左边缘的距离
* getWidth() - getPaddingRight() 计算删除图标右边缘到控件左边缘的距离
*
* isInnerHeight:点击处y坐标是否在删除图标上
* distance 删除图标顶部边缘到控件顶部边缘的距离
* distance + height 删除图标底部边缘到控件顶部边缘的距离
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (getCompoundDrawables()[2] != null) {
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 isInnerWidth = x > (getWidth() - getTotalPaddingRight()) && x < (getWidth() - getPaddingRight());
boolean isInnerHeight = y > distance && y < (distance + height);
if (isInnerWidth && isInnerHeight) {
this.setText("");
}
}
}
return super.onTouchEvent(event);
}

/**
* 当ClearEditText焦点发生变化的时候,
* 输入长度为零,隐藏删除图标,否则,显示删除图标
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFoucs = hasFocus;
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
}

public void setHasFoucs(boolean hasFoucs) {
this.hasFoucs = hasFoucs;
}

protected void setClearIconVisible(boolean visible) {
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0],
getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}

public void setClearIconVisibleP(boolean visible) {
setClearIconVisible(visible);
}

@Override
public void onTextChanged(CharSequence s, int start, int count, int after) {
if (hasFoucs) {
setClearIconVisible(s.length() > 0);
}
}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {

}

@Override
public void afterTextChanged(Editable s) {

}

}
坚持原创技术分享,您的支持是对我最大的鼓励!