ListView中带有CheckBox时,解决CheckBox重复选择问题的一个不错方案

在ListView中,结合CheckBox实现选中项管理,通过在数据模型中添加isSelected属性记录状态,点击事件中更新该属性并同步到列表,避免遍历整个列表,提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先要说明的是,我的ListView自己带有点击事件OnItemClickListener,比如点击其中一项时跳转到另一个页面。而checkBox只是为了选中这一项以待批量处理。因此点击item时并不会影响checkBox。

下面是我的ListView(一个歌曲列表) item的布局,显示歌曲信息,然后后面有一个CheckBox

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants" >
    
    <RelativeLayout 
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:id="@+id/music_info_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    <TextView 
        android:id="@+id/music_name_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textSize="15sp"
        android:maxEms="15"
        android:text="示例歌曲名"
        android:ellipsize="end"/>
    <TextView 
        android:id="@+id/music_singer_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="10sp"
        android:text="歌手名"
        android:layout_below="@id/music_name_localmusic"
        android:textColor="#757575"/>
    <TextView 
        android:id="@+id/music_time_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="10sp"
        android:text="03:25"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="20dp"/>
    <FrameLayout 
        android:id="@+id/music_line_localmusic"
        android:layout_alignBottom="@id/music_singer_localmusic"
        android:layout_toRightOf="@id/music_singer_localmusic"
        android:layout_width="1dp"
        android:layout_height="10dp"
        android:layout_marginLeft="2dp"
        android:layout_marginBottom="1dp"
        android:layout_marginRight="2dp"
        android:background="#000000"
        ></FrameLayout>
    <TextView 
        android:id="@+id/music_album_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="10sp"
        android:text="示例专辑test"
        android:layout_toRightOf="@id/music_line_localmusic"
        android:layout_below="@id/music_name_localmusic"
        android:textColor="#757575"
        />
    </RelativeLayout>
    
    <CheckBox 
        android:id="@+id/music_check_localmusic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
实现ListView最重要的部分当然是写Adapter,下面是我的Adapter类

	private class BaseListAdapter extends BaseAdapter{

		private List<MusicInfo> musicList=new ArrayList<MusicInfo>();
		public BaseListAdapter(List<MusicInfo> list) {
			// TODO Auto-generated constructor stub
			musicList=list;
		}
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return musicList.size();
		}

		@Override
		public Object getItem(int arg0) {
			// TODO Auto-generated method stub
			return musicList.get(arg0);
		}

		@Override
		public long getItemId(int arg0) {
			// TODO Auto-generated method stub
			return arg0;
		}

		@Override
		public View getView(final int position, View theView, ViewGroup arg2) {
			ViewHolder viewHolder=null;
			if(theView==null){
				viewHolder=new ViewHolder();
				theView=getLayoutInflater().inflate(R.layout.musiclist_item, null);
				viewHolder.musicNameText=(TextView)theView.findViewById(R.id.music_name_localmusic);
				viewHolder.singerNameText=(TextView)theView.findViewById(R.id.music_singer_localmusic);
				viewHolder.musicTimeText=(TextView)theView.findViewById(R.id.music_time_localmusic);
				viewHolder.musicAlbumText=(TextView)theView.findViewById(R.id.music_album_localmusic);
				viewHolder.itemCheckBox=(CheckBox)theView.findViewById(R.id.music_check_localmusic);				
				theView.setTag(viewHolder);
			}else {
				viewHolder=(ViewHolder)theView.getTag();
			}
			//给控件加载数据
			final MusicInfo selectedMusic=musicList.get(position);
			viewHolder.musicNameText.setText(selectedMusic.getMusicName());
			viewHolder.singerNameText.setText(selectedMusic.getMusicSinger());
			viewHolder.musicTimeText.setText(selectedMusic.getMusicLength());
			viewHolder.musicAlbumText.setText(selectedMusic.getMusicAlbum());
			if(musicList.get(position).getSelected()){
				viewHolder.itemCheckBox.setChecked(true);
			}else {
				viewHolder.itemCheckBox.setChecked(false);
			}
			viewHolder.itemCheckBox.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					if(selectedMusic.getSelected()){
						selectedMusic.setSelected(false);
						selectedMusicList.remove(selectedMusic);
					}else {
						selectedMusic.setSelected(true);
						selectedMusicList.add(selectedMusic);
					}
					showButtonView();
				}
				
			});
			return theView;
		}
		class ViewHolder{
			TextView musicNameText;
			TextView singerNameText;
			TextView musicTimeText;
			TextView musicAlbumText;
			CheckBox itemCheckBox;
		}
		
	}

可以看到和一般的Adapter写法没有多少区别。唯一不同的是,在给CheckBox加载数据的时候,做了一个判断。

是的,我只是给数据多加了一个属性,以记录CheckBox的选中状态。

比如我这里是显示歌曲信息。我定义了一个MusicInfo类,这个类有musicName(歌曲名),singerName(歌手名),Album(专辑名)等等属性,除此之外,我还多添加了一个boolean属性 isSelected,并默认为false即未被选中状态。然后我定义了一个List<MusicInfo>集合以存储被选中的歌曲,即上面代码中的selectedMusicList集合。

在CheckBox初始化的时候,如果该歌曲的isSelected属性为true,则CheckBox.setChecked(true); 如果isSeleceted属性为false,则CheckBox.setChecked(false);

在Checkbox的OnClick事件中,如果isSelected属性为true,则将它改为false,并把这首歌从selectedMusicList集合中移除。如果isSelected属性为false,则将它改为true,并将这首歌添加到selectedMusicList集合中。

这样,每一首歌的对应的CheckBox是否被选中就被完美地保存了下来,在CheckBox初始化的时候再判断一下就可以了。而CheckBox被选中的歌曲被单独保存到了一个列表selectedMusicList中,如果要对被选中的歌曲做处理,只需要对这个列表进行操作就可以了,是不是很方便呢?

我这几天也看了不少博客,我觉得这种处理方式是最简单易懂的,而且性能也不错,不需要像有些方法那样遍历整个歌曲列表的数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值