Android笔记本自定义控件

两个Recyclerview关联,二级列表实现(两种思路)

2019-05-10  本文已影响195人  空丶_0b92

最近的项目中,有个需求,直接上图。


需求.png

要求,二级列表 并且需要关联,省级和市级列表,支持多选,多选市级,和切换省级之后在继续点击市级,最多只能点击五个

第一种思路:

省级的Recyclerview,市级的Recyclerview,两个adapter,点击省级的时候加载市级列表时候,是重新请求的,adapter也重新刷新。然后市级Recyclerview选中的时候,把bean里的isselect更改状态,然后在刷新adapter,这样 市级多选列表就出来了。


市级列表点击事件.png

1.先用isselect判断是否是选中状态,如果未选中状态用mSelectCityList去装已选中的市级节点,并判断最多只能是五个,要么提示。
2.如过是选中状态,那么此时点击就是删除了,但是这里直接用mSelctCityList.remove(mProvinceCityList.get(mCityPosition)),是不可以的,随然上面用mSelectCityList.add(mProvinceCityList.get(mCityPosition));添加过点击的节点,但是这里要注意一个事:添加的和删除的不是一个对象,内存地址是不同的,所以在这里留下了第一个坑,好,我们继续往下写。
3.单个省份的多选,已经按照上面写完了,那接下来就是切换省份的时候, 要保存以前的状态,那么我们可以想到,mSelectCityList.add(mProvinceCityList.get(mCityPosition))这个里面已经装过我们所保存的对象了,那么我们是否可以直接用呢,答案是,可以的,可以直接用,但是一定要记住:要循环去对比ID值,不能直接用对象. 如下图:

市级列表获取数据源.png
因为我们每次切换省份的时候mProvinceCityList都会被重新赋值,所以内存地址又是不一样的,所以就这里,我们只能去用值比对,那么怎么去用值比对呢,最简单的办法,去循环对比。
循环对比.png .
循环对比,是否有想同的城市名字,有相同的话,那咱们在adapter里去判断并更新他的颜色。
1.png
image.png

我们这里看到了,不仅添加的时候需要判断,删除的时候也需要判断去重置值,做到这已经晕菜了。但是市级列表的需求也差不多达到了,然后省级的写法我就不列了,和市级一样,如法炮制。

这时候问题来了, 发现点击切换或者之后在切换回来,重新选择时候不亮,状态没改变,说内心话,我此时已经崩溃了, 因为感觉这样写太麻烦了,细心的人已经发现了,问题可能又出现在对象的内存地址不同, 不是同一个对象,所以添加或者删除的时候出现了问题。啊!又是这个问题,就在此时,决定放弃此刻的写法,换一种别的高效的方法吧,这时候和我们组长聊天,说到了这个问题,他一句很经典的话点醒了我你要保证父类的唯一性啊,你管它选是谁呢,先去想父列表下的子列表有没有东西啊,唯一性,重复性,那不就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就可以了。
首先,我们来看下子列表添加城市:

定义两个id.png

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的话代表这个省份下面有一个选中的。

点击添加城市.png
用HashMap我们可以直观的去判断,如果数量大于5,那么就是选择超过5个了,如果没有超过,那么点击一个就放进去一个,但是如果是重复点击同一个,那我们怎么知道我们是删除还是添加呢,此时就简单了,直接在最开始的时候去判断。
点击删除.png
如果城市的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里直接给移除掉,因为它已经没有选中的了,所以此时要刷新下省级的显示状态。


省级的显示状态.png

因为省级是单选,切多状态显示,所以判断的时候用||去并联两个条件。

这样一来基本就结束了,我们的二级列表关联多选的需求就做的差不多了,。
心得:在这种有唯一性,切不重复的情况下,能用HashMap就不要用List。而且一定要记住,对象如果不相同,那么去操作的话是没有用的,此时就要用循环对比值。

上一篇下一篇

猜你喜欢

热点阅读