下拉框筛选控件(类似美团)

Demo效果:

307963-588c68a0a4db185a.gif

效果图.gif

工程结构图:

307963-97fa9a27aa16c8e2.png

结构图.png

1.模拟组装数据,因为可能是多层的,所以我们这里通过组合模式来组装数据。在MMBaseItem里面我们定义了三个枚举:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//这个字段我们暂时留着以后扩展,覆盖可能要有些选项不能选择,显示灰色的情况
typedef NS_ENUM(NSUInteger, MMPopupViewMarkType) {   //选中的状态
     MMPopupViewDisplayTypeSelected = 0,       //可以选中
     MMPopupViewDisplayTypeUnselected = 1,     //不可以选中
};
 
typedef NS_ENUM(NSUInteger, MMPopupViewSelectedType) {      //是否支持单选或者多选
     MMPopupViewSingleSelection,                             //单选
     MMPopupViewMultilSeMultiSelection,                     //多选
};
 
typedef NS_ENUM(NSUInteger, MMPopupViewDisplayType) {   //分辨弹出来的view类型
     MMPopupViewDisplayTypeNormal = 0,                 //一层
     MMPopupViewDisplayTypeMultilayer = 1,             //两层
     MMPopupViewDisplayTypeFilters = 2,                //混合
};

每个MMItem都持有一个layout对象提前计算好弹出视图的布局信息并储存。由于MMPopupViewDisplayTypeNormal和MMPopupViewDisplayTypeMultilayer两种类型布局比较单一简单,所以layout对象暂时只是在MMPopupViewDisplayTypeFilters时有用。

当然我这里是模拟数据。下面给出一种建立树模型的思路:

307963-7708a77530870004.png


1.1 首先我们把上图的根节点放到队列中

307963-ae6a2e9ef9e6df53.png

1.2 根据A持有子节点的指针把B,C放进队列,相当于把B,C添加到A的childrenNodes。然后把A给移出队列。

307963-5cfa962948165968.png

1.3 然后按照上面的逻辑一个一个的遍历每个节点。直到队列为空的时候代表一颗建立完毕。下面图未给全,只是部分状态的时刻图。

307963-4380f8b8e57539c9.png

307963-4f08f95a88d1887c.png

2.初始化视图:

1
2
3
4
5
  MMComBoBoxView *view = [[MMComBoBoxView alloc] initWithFrame:CGRectMake(0, 64, kScreenWidth, 40)];
     view.dataSource = self;
     view.delegate = self;
     [self.view addSubview:view];
     [view reload];

3.通过datasource协议将数据传给MMComBoBoxView,你可以联想UITableView数据驱动方式就可以了。

1
2
3
4
5
6
7
#pragma mark - MMComBoBoxViewDataSource
- (NSUInteger)numberOfColumnsIncomBoBoxView :(MMComBoBoxView *)comBoBoxView {
     return  self.mutableArray.count;
}
- (MMItem *)comBoBoxView:(MMComBoBoxView *)comBoBoxView infomationForColumn:(NSUInteger)column {
     return  self.mutableArray[column];
}

4.我们会通过MMComBoBoxViewDelegate协议把选中的路径回调出来,这里我们选择回调存储路径的数组的本质是在于可能开发人员上传的不止是title,可能还有对应的code等一系列的字段。这样方便扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#pragma mark - MMComBoBoxViewDelegate
- (void)comBoBoxView:(MMComBoBoxView *)comBoBoxViewd didSelectedItemsPackagingInArray:(NSArray *)array atIndex:(NSUInteger)index {
     MMItem *rootItem = self.mutableArray[index];
     switch  (rootItem.displayType) {
         case  MMPopupViewDisplayTypeNormal:
         case  MMPopupViewDisplayTypeMultilayer:{
             //拼接选择项
             NSMutableString *title = [NSMutableString string];
            __block NSInteger firstPath;
             [array enumerateObjectsUsingBlock:^(MMSelectedPath * path, NSUInteger idx, BOOL * _Nonnull stop) {
                 [title appendString:idx?[NSString stringWithFormat:@ ";%@" ,[rootItem findTitleBySelectedPath:path]]:[rootItem findTitleBySelectedPath:path]];
                 if  (idx == 0) {
                 firstPath = path.firstPath;
               }
             }];
             NSLog(@ "当title为%@时,所选字段为 %@" ,rootItem.title ,title);
             break ;}
             
         case  MMPopupViewDisplayTypeFilters:{
             [array enumerateObjectsUsingBlock:^(MMSelectedPath * path, NSUInteger idx, BOOL * _Nonnull stop) {
                 //当displayType为MMPopupViewDisplayTypeFilters时有MMAlternativeItem类型和MMItem类型两种
                 if  (path.isKindOfAlternative == YES) {  //MMAlternativeItem类型
                     MMAlternativeItem *alternativeItem = rootItem.alternativeArray[path.firstPath];
                     NSLog(@ "当title为%@时,选中状态为 %d" ,alternativeItem.title,alternativeItem.isSelected);
                 else  {
                     MMItem *firstItem = rootItem.childrenNodes[path.firstPath];
                     MMItem *SecondItem = rootItem.childrenNodes[path.firstPath].childrenNodes[path.secondPath];
                     NSLog(@ "当title为%@时,所选字段为 %@" ,firstItem.title,SecondItem.title);
                 }
             }];
             break ;}
             
         default :
             break ;
     }
}

如果你觉得这篇文章对你有所帮助,欢迎like或star!谢谢!

demo地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值