选择列表请对CheckBox说No

由来

  我记得刚学习Android的时候,有个需求是这个样子的,做一个单选或者多选的选择列表。然后那个时候懂得不是很多,就用CheckBox去做。做来做去,发现很多的坑,比如控件会被重用,导致选中的状态也被重用了。后来随着自己接触的东西变多,想到用另外一种方式来实现选择列表,但是这并不是我写这篇文章的原因。主要原因是最近在看同事写的代码(我们是两个人在开发)的时候,发现选择列表还是用的CheckBox,我觉得有必要分享下自己的实现方式,当然如果你们有什么好的建议记得及时告诉我。

实现方式

  接下来我就说一下我是如何实现选择列表的(欢迎大家来吐槽)。先来一张效果图,比较简单。
效果图
github项目地址

level-list

  官方文档的介绍请戳这里。它可以通过一些值来管理一系列的图片,然后通过level属性修改这些值后就会显示对应的图片。

举个栗子

  因为是选择列表,那必然会有两张图片,一张是未选中的,我们记为ic_select_off,一张是选中的,我们记为ic_select_on。然后我们可以在drawable文件夹下新建一个level_list_common_select.xml的资源文件。具体代码如下

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">

<item
android:drawable="@mipmap/ic_select_off"
android:maxLevel="0"/>

<item
android:drawable="@mipmap/ic_select_on"
android:maxLevel="1"/>

</level-list>

布局文件

  接下来,我们说说布局文件,我们不会用到CheckBox,这里我们用ImageView来顶替CheckBox,大致如下所示。

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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ffffff"
android:orientation="horizontal"
android:paddingLeft="12dp"
android:paddingRight="12dp">

<ImageView
android:id="@+id/selectStatusIv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/level_list_common_select"/>

<TextView
android:id="@+id/selectTitleTv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:paddingLeft="12dp"
android:singleLine="true"
android:textColor="#333333"
android:textSize="16sp"/>

</LinearLayout>

  这里并没有太多花里胡哨的东西,只是用一个ImageView替换掉了CheckBox。

核心逻辑

  你需要找一个能够唯一标记这个选项的字段,比如id,这个字段一般都会有。然后我们的适配器里面会存放一个selectId,在渲染View的方法中校验当前项的id是否和选中的id是一致的,如果一致,则将level设置为1,否则设置为0就可以了。

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
package com.yanfangxiong.levellistimplementselectlist

import android.content.Context
import android.view.View
import com.guoshujinfu.mobile.gscloud.migration.adapter.CommonListAdapter
import kotlinx.android.synthetic.main.listitem_select.view.*

/**
* @author fxYan
*/
class SelectListAdapter(
context: Context,
resId: Int,
data: List<SelectBean>
) : CommonListAdapter<SelectBean>(context, resId, data) {

private var selectId: Long? = null

fun setSelected(selectId: Long) {
this.selectId = selectId
}

override fun bindData(view: View, position: Int, data: SelectBean) {
view.selectStatusIv.drawable.level = if (data.id == selectId) 1 else 0
view.selectTitleTv.text = data.title
}

}

  这里用的kotlin编写的,CommonListAdapter可以去看之前写的用kotlin封装的适配器。这样这个单选的逻辑就写完了。嗯,就是这么简单,不用关心CheckBox重用导致的状态复用问题。

总结

  如果我不去思考该如何简化,那我永远都只是死板的用CheckBox来完成选择列表。所以,要学会思考,只根据产品给的需求完成相应的任务那是一个初级程序猿做的事情。
日子还长,别太失望~

本文标题:选择列表请对CheckBox说No

文章作者:严方雄

发布时间:2018-01-05

最后更新:2018-09-13

原始链接:http://yanfangxiong.com/2018/01/05/选择列表请对CheckBox说No/

0%