IOS实现简易版的QQ下拉列表
程序员文章站
2023-12-16 19:11:22
下面我们通过实例代码来一步步看怎么实现, 首先建立了两个模型类, 一个friend, 一个friendgroup类. 数据源用的本地的一个plist文件. plist文件中...
下面我们通过实例代码来一步步看怎么实现, 首先建立了两个模型类, 一个friend, 一个friendgroup类. 数据源用的本地的一个plist文件. plist文件中包含了friendgroup的name,friends数组等属性.
friend.h 示例代码
#import <foundation/foundation.h> @interface friend : nsobject @property (nonatomic, copy) nsstring *name; @end
friendgroup.h 示例代码
#import <foundation/foundation.h> @interface friendgroup : nsobject @property (nonatomic, copy) nsstring *name; // 数组中存放的为friend类的实例对象 @property (nonatomic, copy) nsmutablearray *friends; // 用来判断分组是否打开(opened属性正是实现下拉列表的关键) @property (nonatomic, assign, getter = isopened) bool opened; // 自定义方法用来赋值 -(void)setfriendgroupdic:(nsmutabledictionary *)dic; @end
friendgroup.m 示例代码
#import "friendgroup.h" #import "friend.h" @implementation friendgroup -(void)setfriendgroupdic:(nsmutabledictionary *)dic { // 通过字典给friendgroup的属性赋值 [self setvaluesforkeyswithdictionary:dic]; nsmutablearray *temparray = [nsmutablearray array]; // 遍历friends属性数组 for (nsmutabledictionary *dic in self.friends) { friend *friend = [[friend alloc] init]; [friend setvaluesforkeyswithdictionary:dic]; [temparray addobject:friend]; } //重新对friends属性数组赋值,此时存的都是friend对象 self.friends = [nsmutablearray arraywitharray:temparray]; } @end
在viewcontroller中创建一个tableview
#import "viewcontroller.h" #import "sectionview.h" #import "friendgroup.h" #import "friend.h" #define ktableviewreuse @"reuse" @interface viewcontroller ()<uitableviewdelegate, uitableviewdatasource, sectionviewdelegate> @property (nonatomic, strong) uitableview *tableview; // 数组中存放friendgroup的实例对象 @property (nonatomic, strong) nsmutablearray *allarray; @end @implementation viewcontroller - (void)viewdidload { [super viewdidload]; self.allarray =[nsmutablearray array]; [self creattableview]; [self getdata]; } - (void)creattableview { self.tableview = [[uitableview alloc] initwithframe:self.view.bounds style:uitableviewstyleplain]; _tableview.delegate = self; _tableview.datasource = self; [_tableview registerclass:[uitableviewcell class] forcellreuseidentifier:ktableviewreuse]; [self.view addsubview:_tableview]; } // 获取数据 - (void)getdata { nsstring *filepath = [[nsbundle mainbundle] pathforresource:@"friends.plist" oftype:nil]; nsarray *temparray = [nsarray arraywithcontentsoffile:filepath]; for (nsmutabledictionary *dic in temparray) { friendgroup *friendgroup = [[friendgroup alloc] init]; [friendgroup setfriendgroupdic:dic]; [self.allarray addobject:friendgroup]; } [self.tableview reloaddata]; } - (cgfloat)tableview:(uitableview *)tableview heightforheaderinsection:(nsinteger)section { return 50; } // sectionview必须实现的协议方法 - (void)touchaction:(sectionview *)sectionview { } #pragma mark - tableview delegate -(uiview *)tableview:(uitableview *)tableview viewforheaderinsection:(nsinteger)section { friendgroup *friendgroup = [self.allarray objectatindex:section]; //放一个封装的view,view上有一个label和imageview,自带touch事件,点击触发协议方法 sectionview *sectionview = [[sectionview alloc] initwithframe:cgrectmake(0, 0, 375, 50)]; sectionview.delegate = self; sectionview.tag = section + 1000; sectionview.textlabel.text = friendgroup.name; sectionview.group = friendgroup; return sectionview; } #pragma mark - tableview datasource - (nsinteger)numberofsectionsintableview:(uitableview *)tableview { return _allarray.count; } - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { return [_allarray[section] friends].count; } - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:ktableviewreuse]; friendgroup *friendgroup = _allarray[indexpath.section]; friend *friend = friendgroup.friends[indexpath.row]; cell.textlabel.text = friend.name; return cell; } #pragma mark - memory waring - (void)didreceivememorywarning { [super didreceivememorywarning]; // dispose of any resources that can be recreated. } @end
可以从上面代码看到, 创建了一个tableview. 并根据数组个数给分区数量赋值, 然后在tableview: viewforheaderinsection:
方法里, 用一个自定的view给分区头视图赋值. 在tableview: cellforrowatindexpath:
方法里给每个分区对应的cell进行了赋值. 先看一下效果.
从上图可以看到现在每个分区中对应有不同数量的row,但是还没有实现我们想要的效果.所以再往下继续看.
sectionview.m
-(void)touchesbegan:(nsset *)touches withevent:(uievent *)event { [self.delegate touchaction:self]; } /* [self.delegate touchaction:self]; 协议方法会刷新tableview,然后会刷新tableview的 viewforheaderinsection:方法 就会重新布局sectionview所以会走layoutsubviews方法 */ -(void)layoutsubviews { [super layoutsubviews]; // 改变imageview的transform属性 点击时有开闭的效果 [uiview animatewithduration:0.3 animations:^{ _imageview.transform = _group.opened ? cgaffinetransformmakerotation(m_pi_2) : cgaffinetransformmakerotation(0); }]; }
点击sectionview时 就让代理人去执行协议方法,但是在vc的协议方法中什么都没写, 所以需要完善一下
- (void)touchaction:(sectionview *)sectionview { // 通过前面设置的tag值找到分区的index nsinteger index = sectionview.tag - 1000; friendgroup *group = [self.allarray objectatindex:index]; // 每次点击, 状态变为与原来相反的值 group.opened = !group.isopened; [self.tableview reloadsections:[nsindexset indexsetwithindex:index] withrowanimation:uitableviewrowanimationnone]; }
我们平时用的qq下拉列表, 未打开时不显示好友, 打开后才展示好友列表. 所以应该在numberofrowsinsection
方法中要进行设置.
- (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { friendgroup *group = [self.allarray objectatindex:section]; // 如果未打开 count为0 如果打开 count为group的属性数组对应的个数 nsinteger count = group.isopened ? group.friends.count : 0; return count; }
效果如下图
总结
以上就是ios实现简易版的qq下拉列表的全部内容,效果虽然很简单,但还会希望对大家开发ios有所帮助。