问题描述
最近在写一个商城项目的购物车模块。里面有checkbox的全选与取消全选功能。然后checkbox是在recyclerview中的。而且还不止一层。写的我身心俱疲。中间遇到了很多问题,checkbox全选问题只是其中一个,在这里记录下,其他问题,也会记录。
样式是这样。
78751997abc7d2ca984bb3841cbd458.png
首先因为复用问题,每个item的数据对应着一个isChecked的属性。
里面的black/64G对应的条目我是通过linearlayout进行addview实现的。设置的监听只能通过回调。另外说一句,一个购物车让我对接口回调有了新的认识。哈哈。
image.png
默认全选按钮是选中的。然后判断子元素是否有未选中。有则全选按钮为false。全选按钮的监听事件好写。把item中的ischecked设为对应的true或者false。然后notify一下item即可。问题出现在,按钮全选的状态下,点击子元素的选中按钮。使其变为非全选状态。我心想也没问题呀。就如代码中显示的。加一个监听,改变全选按钮的状态为false,
//设置spu选中
itemBean.isChecked = allChecked; //此时allChecked=false
checkBox.setChecked(itemBean.isChecked); //非选中
这时候就出现问题,因为我们给全选按钮添加的监听事件里面。是按照点击全选按钮来处理的,那么全选按钮设置为false的话,所有的按钮都变为false非选中了。这显然不是想要的效果。
解决方法
我在想有木有一个方法来判断是checkBox.setChecked触发全选按钮的监听还是用户点击了全选按钮来触发的监听呢。因为这正是区分的关键。网上搜了很多文章。发现没有是这样处理的。有些写的很乱,有一些方案就是动态设置checkbox的监听事件。子元素点击的时候设为null,就不触发。然后点完之后再重新设置正常要的监听。 这很明显不合理。而且在一些复杂场景下。并不是把方法写在哪里都能拿到想要的参数。
后来发现有个isPressed()方法。可以判断是用户点击触发的事件还是其他设置触发的。试了一下。正是想要的效果。如下。
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (!buttonView.isPressed()) { //判断view是否是用户点击
return;
}
item.isChecked = isChecked;
//设置sku商品是否选中
for (int i = 0; i < item.skuList.size(); i++) {
item.skuList.get(i).isChecked = isChecked;
}
checkBox.post(() -> {
notifyItemChanged(position); //notify一下。
});
mOnPriceChangedListener.onAllChecked();
mOnPriceChangedListener.onPriceChange();
});
如果是用户点击。则进行下面的处理。把子元素全选等。
如果不是用户点击的全选。而是点击子元素触发的全选费全选。则直接return掉。
总结
当时看了很多文章。真没有看到这个api。包括现在我搜这个api的用法的文章也不多。可能checkbox在平时开发中用的比较少。全选更是少。所以不多吧。所以记录下。
可以看出google还是考虑的很全面的。有很多的api很好用。多看源码。增加熟悉度。可以在遇到一些场景的时候可以想起一些意想不到的很好用的解决方法。
网友评论