最近的项目中,有个需求,直接上图。
要求,二级列表 并且需要关联,省级和市级列表,支持多选,多选市级,和切换省级之后在继续点击市级,最多只能点击五个
第一种思路:
省级的Recyclerview,市级的Recyclerview,两个adapter,点击省级的时候加载市级列表时候,是重新请求的,adapter也重新刷新。然后市级Recyclerview选中的时候,把bean里的isselect更改状态,然后在刷新adapter,这样 市级多选列表就出来了。
1.先用isselect判断是否是选中状态,如果未选中状态用mSelectCityList去装已选中的市级节点,并判断最多只能是五个,要么提示。
2.如过是选中状态,那么此时点击就是删除了,但是这里直接用mSelctCityList.remove(mProvinceCityList.get(mCityPosition))
,是不可以的,随然上面用mSelectCityList.add(mProvinceCityList.get(mCityPosition))
;添加过点击的节点,但是这里要注意一个事:添加的和删除的不是一个对象,内存地址是不同的,所以在这里留下了第一个坑,好,我们继续往下写。
3.单个省份的多选,已经按照上面写完了,那接下来就是切换省份的时候, 要保存以前的状态,那么我们可以想到,mSelectCityList.add(mProvinceCityList.get(mCityPosition))
这个里面已经装过我们所保存的对象了,那么我们是否可以直接用呢,答案是,可以的,可以直接用,但是一定要记住:要循环去对比ID值,不能直接用对象. 如下图:
因为我们每次切换省份的时候
mProvinceCityList
都会被重新赋值,所以内存地址又是不一样的,所以就这里,我们只能去用值比对,那么怎么去用值比对呢,最简单的办法,去循环对比。循环对比,是否有想同的城市名字,有相同的话,那咱们在adapter里去判断并更新他的颜色。
我们这里看到了,不仅添加的时候需要判断,删除的时候也需要判断去重置值,做到这已经晕菜了。但是市级列表的需求也差不多达到了,然后省级的写法我就不列了,和市级一样,如法炮制。
这时候问题来了, 发现点击切换或者之后在切换回来,重新选择时候不亮,状态没改变,说内心话,我此时已经崩溃了, 因为感觉这样写太麻烦了,细心的人已经发现了,问题可能又出现在对象的内存地址不同, 不是同一个对象,所以添加或者删除的时候出现了问题。啊!又是这个问题,就在此时,决定放弃此刻的写法,换一种别的高效的方法吧,这时候和我们组长聊天,说到了这个问题,他一句很经典的话点醒了我你要保证父类的唯一性啊,你管它选是谁呢,先去想父列表下的子列表有没有东西啊
,唯一性,重复性,那不就HashMap了么?
对,第二种思路,简单高效的思路:
HashMap
分析:首先,我们有父子两个列表,那我们此时应该定义两个HashMap,一个装子类选中的,一个装父类下有几个子类被选中,简单来说就是,
1.第一个private HashMap<String, Object> mCityHashMap;
,这个mCityHashMap
的key是我当前市级列表的城市ID,就和第一种思路里去对比城市名称一样,这里的key就是当前城市的对象。
2.第二个:private HashMap<String, Integer> mProvinceHashMap;
,这个mProvinceHashMap
的key装的是此城市的父级ID,就是对应的省份ID,而value就有意思了,装的是个Interger类型的,那么装的是什么呢, 用temp变量表示的话,里面装的就是有几个被点击,不管你点击的是哪个城市,反正只要点击了,我就装你城市的父类,和一个temp的次数,这样来说,哇,简直不要太简单了,反正只用控制好这个hashmap就可以了,反正hashmap有不重复性,唯一性,key只要相同的话,值是会被替换的,所以我们控制好key就可以了。
首先,我们来看下子列表添加城市:
String mCityNo = mProvinceCityList.get(position).getAreaNo();
String mCityParentNo = mProvinceCityList.get(position).getAreaParent();
Integer temp = mProvinceHashMap.get(mCityParentNo);
第一个mCityNo
是城市的ID,第二个mCityParentNo
是城市的父类id,也就是省的ID
而这个temp就是通过城市的父类ID去到mProvinceHashMap
里去找值,看此时有没有添加的值,如果是0,那么则代表一个没有,如果有1的话代表这个省份下面有一个选中的。
用HashMap我们可以直观的去判断,如果数量大于5,那么就是选择超过5个了,如果没有超过,那么点击一个就放进去一个,但是如果是重复点击同一个,那我们怎么知道我们是删除还是添加呢,此时就简单了,直接在最开始的时候去判断。
如果城市的hashmap里有包含这个城市的id,那么就带表这个城市被添加进去过,此时直接删除就好。
细讲添加和删除
添加
mCityHashMap.put(mCityNo, mProvinceCityList.get(position));
我们在添加的时候,出了把此时的城市对象和城市id添加进去,还在下面给省级hashmap添加了,因为我们此时已经点击了啊,省级的hashmap是不是要添加一次次数。
if (temp != null) {
int val = temp.intValue();
mProvinceHashMap.put(mCityParentNo, new Integer(++val));
} else {
mProvinceHashMap.put(mCityParentNo, new Integer(1));
}
如果这时候是第一次点击的话,那么就直接new个次数为1,如果不是的话就要把这个数加1(Integer类型不能直接运算,所以要先成Int类型在去用++运算)
在adapter里也是用直接去判断是否包含这个城市,这里简单,直接上代码
if (mHashMap.containsKey(data.getAreaNo())){
mTvProvinceCity.setTextColor(Color.parseColor("#5f8dc9"));
mTvProvinceCity.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.com_icon_selected01, 0);
}else {
mTvProvinceCity.setTextColor(Color.parseColor("#222222"));
mTvProvinceCity.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
删除
删除则和添加完全相反(这不是屁话么),上代码
if (mCityHashMap.containsKey(mCityNo)) {
mCityHashMap.remove(mCityNo);
if (temp != null) {
int val = temp.intValue();
if (--val == 0) {
mProvinceHashMap.remove(mCityParentNo);
} else {
mProvinceHashMap.put(mCityParentNo, new Integer(val));
}
}
}
可以看到,删除和添加一样,如果包含了则移除,这里要清楚一个事,如果当此时的val到0的时候,一定要把省级hash里直接给移除掉,因为它已经没有选中的了,所以此时要刷新下省级的显示状态。
因为省级是单选,切多状态显示,所以判断的时候用||去并联两个条件。
这样一来基本就结束了,我们的二级列表关联多选的需求就做的差不多了,。
心得:在这种有唯一性,切不重复的情况下,能用HashMap就不要用List。而且一定要记住,对象如果不相同,那么去操作的话是没有用的,此时就要用循环对比值。