自定义View之使用DrawableState实现选择框

前言

本篇主要记录一下有两种状态(选中、未选中)图标的ImageView。通过点击可以切换状态。

主要记录源码。其中主要的代码是CheckableImageView.java,其中的主要代码也写有注释,这里就不啰嗦了。

详细代码

CheckableImageView.java

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

/**
* <pre>
* author : Haitao
* blog : http://www.nhtzj.com
* time : 2018/8/14
* desc : 选中、未选中图标的ImageView
* version: 1.0
* </pre>
*/
public class CheckableImageView extends AppCompatImageView implements Checkable, View.OnClickListener {

private OnViewListener mListener;

private boolean mChecked;
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};

public CheckableImageView(Context context) {
this(context, null);
}

public CheckableImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CheckableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

//若未指定切换的图标,则使用默认的
Drawable drawable = getDrawable();
if (drawable == null) {
setImageResource(R.drawable.check_button);
}

//设置点击监听,这样即使用户没有设置回调,本控件也能使用
bindEvent();
}

@Override
public int[] onCreateDrawableState(final int extraSpace) {
if (!isChecked()) {
// 如果未选中,直接返回父类的结果
return super.onCreateDrawableState(extraSpace);
} else {
// 如果选中,将父类的结果和选中状态合并之后返回
int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
return mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
}

@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}

@Override
public boolean isChecked() {
return mChecked;
}

@Override
public void toggle() {
setChecked(!mChecked);
}

/**
* 重写setOnClickListener方法,将传入的参数进行包装
*
* @param l
*/
@Override
public void setOnClickListener(final OnClickListener l) {
OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
toggle();
if (l != null) {
l.onClick(v);
}
}
};
super.setOnClickListener(onClickListener);
}

@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onViewClick(v);
}
}

/**
* 绑定点击监听
*/
private void bindEvent() {
setOnClickListener(this);
}

/**
* 设置回调
*
* @param l
*/
public void setListener(OnViewListener l) {
this.mListener = l;
}

/**
* 自定义点击回调
*/
interface OnViewListener {
void onViewClick(View v);
}
}

资源文件

check_button.xml

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:enterFadeDuration="@android:integer/config_shortAnimTime" android:exitFadeDuration="@android:integer/config_shortAnimTime">
<item android:drawable="@drawable/ic_checked" android:state_checked="true" />
<item android:drawable="@drawable/ic_unchecked" android:state_checked="false" />
</selector>

ic_checked.xml

1
2
3
4
5
6
7
8
9
10
11
12
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportHeight="1024"
android:viewportWidth="1024"
tools:ignore="UnusedAttribute,VectorRaster">
<path
android:fillColor="#1FC88B"
android:pathData="M512,64C265.6,64 64,265.6 64,512s201.6,448 448,448 448,-201.6 448,-448S758.4,64 512,64zM755.2,387.2l-294.4,278.4c-12.8,12.8 -32,12.8 -44.8,0L297.6,544c-12.8,-12.8 -12.8,-32 0,-44.8s32,-12.8 44.8,0l96,96 272,-256c12.8,-12.8 32,-12.8 44.8,0s12.8,35.2 0,48z" />
</vector>

ic_unchecked.xml

1
2
3
4
5
6
7
8
9
10
11
12
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportHeight="1024"
android:viewportWidth="1024"
tools:ignore="UnusedAttribute,VectorRaster">
<path
android:fillColor="#1FC88B"
android:pathData="M512,960C265.6,960 64,758.4 64,512S265.6,64 512,64s448,201.6 448,448 -201.6,448 -448,448zM512,896c211.2,0 384,-172.8 384,-384S723.2,128 512,128 128,300.8 128,512s172.8,384 384,384z" />
</vector>

参考

Android 中 View 的中的 DrawableState

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