Demo效果:
效果图.gif
工程结构图:
结构图.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时有用。
当然我这里是模拟数据。下面给出一种建立树模型的思路:
1.1 首先我们把上图的根节点放到队列中
1.2 根据A持有子节点的指针把B,C放进队列,相当于把B,C添加到A的childrenNodes。然后把A给移出队列。
1.3 然后按照上面的逻辑一个一个的遍历每个节点。直到队列为空的时候代表一颗建立完毕。下面图未给全,只是部分状态的时刻图。
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!谢谢!