android 多选功能小姐

多选功能小姐

其实不是小姐,是小节。

这周接到一个需求,完成一个多选删除以及多选转发的功能。删除以及转发的功能已经有了,注意是要实现多选的操作。

先说多选

这里的界面是ListView + CursorAdapter 实现的。我需要在 ListViewItemView 里面加一个CheckBox.

不得不提一下,这里的布局写的非常的混乱。里面包含多种类型的Item的,理论上,使用不同的ItemType去加载不同的ItemView是非常合适的。但是原来的界面不是这样玩的。是直接在一个ItemView里面通过逻辑去判断显示或者隐藏那部分View. 行吧,这样也是可以的,只是布局就比较混乱了。然后更糟糕的是,这里的布局还分左右两种情况,然后布局是同一个布局,然后在代码里面动态改变。具体怎么改的呢?

if (pos == RIGHT) {
    
    lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); // 添加该规则
    lp.addRule(RelativeLayout.RIGHT_OF, 0); // 屏蔽该规则
} else {
   
    lp.addRule(RelativeLayout.RIGHT_OF, R.id.item_check);
    lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
}

这段代码涉及到 RelativeLayout.LayoutParams.addRule()这个方法。这个方法很有意思。尤其是带两个参数的。如果第二个参数是0,说明这个规则不起作用。这样做有什么意义呢?意义就在于,如果之前添加了这个规则,通过这样的方式,可以让之前添加的该规则失效。

先把Checkbox放置到正确的位置。

好了,既然是这样的方式。我的CheckBox又是需要加在每个ItemView的最左边的。那么我就也按照addRule的方式,把我的Checkbox放到对应的位置上面去了。

然后要根据不同的Item类型,设置Checkbox的状态。

分别是不可用,未选中,选中 这3种状态。

这个要怎么弄呢?我先是根据对应的POJO对象,在里面添加一个属性int checkState;去处理的。但是,一直不行,滑动之后,选中状态全部混乱了。我猜想不可行的原因可能是,这里的POJO对象是根据Cursor生成的。而根据Cursor生成,又会将之前设置的checkState恢复为默认值。(这个只是猜想,没有去验证。)

既然此路不通,我就变通一下。我不再去设置对应的POJO对象的checkState属性了。我专门搞了一个成员变量HashMap<Integer,Integer>.其中的映射关系是:{key:position,value:checkState};这样就靠谱了。你不是根据Cursor去生成对应的POJO对象的吗,行。我的position也是通过Cursor拿到的。int position = cursor.getPosition();然后可不可用,是具体原有的逻辑来的。比如:int checkState = item.checkable? 0:1; 这样,可用不可用状态就搞定了。但是,用户点击选中的状态还是没有保存。

那么就通过设置Checkbox的点击事件去做这件事。

cb.setOnclickListener(v->{
    // 代码中将 0,1,2 定义成常量了,这里是为了验证效果
    // 0 - disable
    // 1 - unChekced
    // 2 - checked
	checkMap.put(pos, checkMap.get(pos)==1? 2:1);
	cb.setChecked(checkMap.get(pos) == 2); 
});

好了, 通过设置点击事件,也将CheckBox的选中不选中状态保存了。
到此为止,checkbox的3种状态都搞定了,列表怎么滑动都不会出现选中状态错乱的问题了。

至于样式,这个直接在布局里面设置对应的style去控制的。但是实际上滚动之后,样式不对了,我又在代码里面 cb.setXXX(); 之后调用了cb.setButtonDrawable(R.drawable.cb_multi_selector);

那么,现在就要把之前多选对应的数据给获取到,一遍后续的删除,转发操作的执行。

那么,之前保存的,只是{position:checkState} ,现在要拿到数据,那很简单。根据对应的position以及 checkState == 2然后把对应的POJO对象存起来即可。

做法就是弄一个成员变量private List<Bean> selectedList = new ArrayList<>; , 然后在CheckBox的点击事件里面做对应的list.add(bean); / list.remove(Bean);的操作即可。

cb.setOnClickListener(v->{
	// ... 设置选中状态的逻辑先
	if( checkMap.get(position) == 2 ) {
		selectedList.add(bean);
	} else {
		selectedList.remove(bean);
	}
});

OK , 这样一来,就把选中的数据给保存了。

然后在执行删除的时候,就去执行删除操作:ItemUtils.delete(seletedList);
执行转发的时候,也是去执行转发:ItemUtils.forward(selectedList);

多说一句,在执行多选删除的时候,这里是执行了数据操作。涉及到一个批处理操作。原有的逻辑是删除单条数据的,没有批处理。而这里就需要使用批处理了。不然每次删除一个都会触发删除成功的回调,非常烦人。

这里用到了ContenResolver.applyBatch();的操作。
public ContentProviderResult[] applyBatch(@NonNull String authority,
        @NonNull ArrayList<ContentProviderOperation> operations){}

authority: 这个不用说的, contenProvider 必然会配置这个
operations 这个就是待处理的数据集合

ContentProviderOperation的操作还是比较简单的,没有用过也能立即明白。

这里既然是删除,那就是 ContentProviderOperation.newDelete(uri).build(); 里面还有 withXXX()这样的辅助方法。(我觉得withXXX是给newUpdate()用的。)

这些参数构造完成了,调用一下 ContenResolver.applyBatch(authorty,ops);即可。

至于转发,这里完全是一个原有逻辑,不说了。


这个小姐大致就是这样子了。错了,是小节

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值