android 列表滑动多选,Android实现ListView嵌套Checkbox真正的多选、全选、反选

本文介绍了如何在Android中处理ListView嵌套CheckBox,解决列表滑动时复选框状态错乱的问题。通过创建自定义Adapter,实现ListView项的多选、全选和反选功能,同时提供了相关的布局文件和关键代码示例。

我们在开发APP的时候,很多情况下会使用到ListView嵌套CheckBox的情况,其实很多人要说这个其实很简单了,并没有那么复杂,为什么还要单独用一篇博客来写呢?事实上并非如此,我们在使用ListView嵌套CheckBox复选框的时候会出现很多问题,

废话不多说,直接进入主题,首先我们来看ListView的item的布局文件:

listview_item.xml

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

android:gravity="center">

android:id="@+id/cb_button"

android:checked="false"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:button="@drawable/checkbox_selector"

android:clickable="true"

android:focusable="true"

android:marginLeft="30dp" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textSize="15sp"

android:layout_marginLeft="200dp"

android:text="你好"

android:id="@+id/tv_name"/>

布局文件中使用了一个checkbox复选框和一个textview,这样做是为了解决初学者的疑惑,这里要贴别注意checkbox的xml代码,如果不把android:focusable设置为false的话,会在后面让listview的item无法获得焦点

上面是listview的每个item的布局文件,没什么难度,接下来看看主布局文件:

activity_main.xml

android:layout_width="match_parent"

android:orientation="vertical"

android:layout_height="wrap_content">

android:layout_width="match_parent"

android:layout_marginTop="100dp"

android:layout_height="wrap_content"

android:orientation="horizontal"

>

android:id="@+id/cb_all_button"

android:checked="false"

android:button="@drawable/checkbox_selector"

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:layout_gravity="center_vertical"

android:layout_marginLeft="20dp"

android:text="全选"

android:textSize="15sp"

android:gravity="center_vertical"

android:paddingLeft="10dp"

android:focusable="false"

android:onClick="allSelect" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:layout_marginLeft="20dp"

android:orientation="horizontal" >

android:id="@+id/btn_fanxuan"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5dp"

android:layout_weight="1"

android:gravity="center"

android:background="@drawable/button_selector"

android:textSize="15sp"

android:text="反选" />

android:id="@+id/btn_cancel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="5dp"

android:layout_weight="1"

android:gravity="center"

android:textSize="15sp"

android:background="@drawable/button_selector"

android:text="取消" />

android:layout_width="match_parent"

android:layout_height="match_parent">

上面的是主界面的布局文件,主文件中放了一个全选的checkbox复选框,和两个按钮用来实现反选和取消,也挺简单的,这里就不多说了,其中的background引用的是资源文件,也就是点击的按钮的效果文件,接下来我们看看主要的代码文件:

Adapter适配器

public class MyListAdapter extends BaseAdapter{

List list = new ArrayList();

private static SparseBooleanArray isSelected;/**用SparseBooleanArray来代替map**/

Context context;

HolderView holderView = null;

/**

* 全选回调接口

*/

CheckedAllListener mListener;

public void setCheckedAllListener(CheckedAllListener listener) {

mListener = listener;

}

public MyListAdapter(List list, Context context) {

// TODO Auto-generated constructor stub

this.context = context;

this.list = list;

isSelected = new SparseBooleanArray();

initData();

}

/**

* 初始化数据

*/

private void initData()

{

for (int i = 0; i < list.size(); i++) {

getIsSelected().put(i, false);

}

}

public static SparseBooleanArray getIsSelected()

{

return isSelected;

}

public static void setIsSelected(SparseBooleanArray isSelected) {

MyListAdapter.isSelected = isSelected;

}

@Override

public int getCount() {

// TODO Auto-generated method stub

return list.size();

}

@Override

public Test getItem(int position) {

// TODO Auto-generated method stub

return list.get(position);

}

@Override

public long getItemId(int position) {

// TODO Auto-generated method stub

return position;

}

@Override

public View getView(final int position, View convertView, ViewGroup parent) {

// TODO Auto-generated method stub

View view = convertView;

if (view == null) {

holderView = new HolderView();

//得到资源文件

LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

view = inflater.inflate(R.layout.listview_item, parent, false);

holderView.cb_button = (CheckBox)view.findViewById(R.id.cb_all_button);

holderView.tv_name = (TextView)view.findViewById(R.id.tv_name);

view.setTag(holderView);

}

else {

holderView = (HolderView)view.getTag();

}

final Test item = getItem(position);

if (item != null) {

holderView.tv_name.setText(item.getName());

holderView.cb_button.setChecked(isSelected.get(position));

}

/**

* 增加checkbox的改变事件,每个item的点击事件

*/

holderView.cb_button.setOnCheckedChangeListener(new OnCheckedChangeListener() {

@Override

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

// TODO Auto-generated method stub

// holderView.cb_button.toggle();

if (buttonView.isPressed()) {

isSelected.put(position,isChecked);

//监听回调,是否改变全选按钮的状态

mListener.CheckAll(isSelected);

}

item.setCheck(isChecked);

}

});

return view;

}

class HolderView

{

private CheckBox cb_button;

private TextView tv_name;

}

/**

* 当所有CheckBox全选时回调

* @author Administrator

*

*/

public interface CheckedAllListener

{

void CheckAll(SparseBooleanArray checkall);

}

}

适配器的内容也比较简单,这里我在适配器中解决了滑动listview出现的checkbox状态错乱的问题,然后增加了一个checkbox的全选回调,就是说每次点击item的复选框都会去调用一下这个借口,来判断对否需要对全选按钮做处理,如果有不懂接口的回调方法,我会在以后的文章中进行讲解,有些不懂的我也用注释标了一下,其中的Test.java比较简单,说白了,就是纯粹的为了好看,帮助大家理解,大家也可以看下:

Test.java

public class Test {

private String name;

private boolean isCheck;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public boolean isCheck() {

return isCheck;

}

public void setCheck(boolean isCheck) {

this.isCheck = isCheck;

}

}

这个也没有啥好介绍的,然后我们再来看看mainActivity.java文件,

mainActivity.java

public class MainActivity extends AppCompatActivity implements MyListAdapter.CheckedAllListener {

MyListAdapter adapter;

ListView listView;

List list;

CheckBox cb_button_all;

Button btn_select;

Button btn_select_cancel;

SparseBooleanArray isCheckeds;

//判断是否全选按钮按下

boolean flag = false;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

listView = (ListView)findViewById(R.id.list_view);

cb_button_all = (CheckBox)findViewById(R.id.cb_all_button);

btn_select = (Button)findViewById(R.id.btn_fanxuan);

btn_select_cancel = (Button)findViewById(R.id.btn_cancel);

setSupportActionBar(toolbar);

isCheckeds = new SparseBooleanArray();

list = new ArrayList<>();

for (int i = 0; i <= 20; i++)

{

Test test = new Test();

test.setName("sister" + i);

list.add(test);

}

adapter = new MyListAdapter(list,this);

adapter.setCheckedAllListener(this);

listView.setAdapter(adapter);

btn_select.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 遍历list的长度,将已选的设为未选,未选的设为已选

for (int i = 0; i < list.size(); i++) {

if (MyListAdapter.getIsSelected().get(i)) {

MyListAdapter.getIsSelected().put(i, false);

} else {

MyListAdapter.getIsSelected().put(i, true);

}

}

// 刷新listview和TextView的显示

adapter.notifyDataSetChanged();

}

});

btn_select_cancel.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 遍历list的长度,将已选的按钮设为未选

for (int i = 0; i < list.size(); i++) {

if (MyListAdapter.getIsSelected().get(i)) {

MyListAdapter.getIsSelected().put(i, false);

}

}

// 刷新listview和TextView的显示

adapter.notifyDataSetChanged();

}

});

}

/**

* 该点击事件放在了xml文件的android:onclick中

* @param v

*/

public void allSelect(View v)

{

System.out.println("========>>>>>>" + cb_button_all.isChecked());

if (cb_button_all.isChecked()) {

flag = true;

}

else {

flag = false;

}

if (flag) {

for (int i = 0; i < list.size(); i++) {

isCheckeds.put(i, true);

MyListAdapter.setIsSelected(isCheckeds);

}

}else {

for (int i = 0; i < list.size(); i++) {

isCheckeds.put(i, false);

MyListAdapter.setIsSelected(isCheckeds);

}

}

//更新适配器

adapter.notifyDataSetChanged();

}

/**

* 全选按钮的回调事件,手否进行全选

* @param checkall

*/

@Override

public void CheckAll(SparseBooleanArray checkall) {

int a = checkall.indexOfValue(false);

int b = checkall.indexOfValue(true);

System.out.println(a + "----" + b);

//判断SparseBooleanArray是否含有true

if (checkall.indexOfValue(true) < 0) {

if (cb_button_all.isChecked()) {

this.flag = false;

cb_button_all.setChecked(false);

}

}else if(checkall.indexOfValue(false) < 0){

if (!cb_button_all.isChecked()) {

this.flag = false;

cb_button_all.setChecked(true);

}

}

else if(checkall.indexOfValue(false) >= 0 && checkall.indexOfValue(true) >= 0){

if (cb_button_all.isChecked()) {

this.flag = true;

cb_button_all.setChecked(false);

}

}

}

}

在mainActivity.java中我实现了checkbox全选的回调,然后设置了一个flag来做一个标识,初始化的时候将所有的checkbox设置为false

效果图

c759b636375f

image.png

喜欢请点击+关注哦

c759b636375f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值