本篇主要讲解仿QQ分组效果的实现,通过本遍的学习,估计都可以自己去实现了(老司机可以),在这里只说仿QQ分组的效果,代码简单,逻辑清晰。其他的功能的可以自行添加,好了,进入主题吧。
效果图
下面的是其效果图
实现原理
1.创建一个表格tableView和对数据的初始化
在这里要说一下,对数据的初始化,因为要实现分组的效果,所以就多加一些数据,可能有人会问笔者,for循环的为什么是26和10,这里笔者要解释一下,26是为了A-Z一一对应的,为了做表格右边的点击。至于10,这个就是每个分区的item的个数。
#pragma mark - 创建表格
- (void)creatTableView {
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, kScreenSize.width, kScreenSize.height-20) style:UITableViewStylePlain];
//设置代理和数据源
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
#pragma mark - 数据
- (void)dataInit {
_dataArr = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < 26; i++) {
//一维数组
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < 10 ; j++) {
//每个内容都有model填充
WSModel *model = [[WSModel alloc] init];
model.name = [NSString stringWithFormat:@"%C%@",(unichar)('A'+i),@"吴松"];
model.QQNumber = @"qq: 3145419760";
model.sex = @"男";
//把模型对象放入数组中
[arr addObject:model];
}
//把一维数组放入数据源
[_dataArr addObject:arr];
}
}
这里是用C语言的话说,是二维数组。这样的好处是减少代码量,如果你的需求的中对数据有别的要求,您可以定义两个数组:sectionArr(分区),cellArr(分区cell的个数)
2.还有一个比较重要的环节
就是为了要对每个分区的是否展开进行一定的标记,所以笔者就这样做了:
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
{
//数据源数组
NSMutableArray *_dataArr;
//记录每个分区 的展开状态 0表示关闭 1表示展开状态
int _sectionStatus[26];//默认:关闭
}
_sectionStatus[26],因为是26个分区,所以就数组里的元素的就是26个,默认的话,都是0,所以初始状态都是关闭状态
3.分区索引的实现
代码如下:
因为是26个分区,所以for循环的次数是26
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (self.tableView != tableView) {
return nil;
}
NSMutableArray * titleArr = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < 26; i++) {
//设置26个分区的索引
[titleArr addObject:[NSString stringWithFormat:@"%C",(unichar)('A'+i)]];
}
[titleArr addObject:@"#"];
//返回一个数组
return titleArr;
}
实现用户点击时,让其tableView的分区滚动到指定的分区位置
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
//选中右侧索引之后 返回 指定分区的索引值
return index;
}
4.分区头视图添加点击事件(重点,关键部分)
显示分区内容,代码如下:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if (self.tableView != tableView) {
return nil;
}
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenSize.width, 40)];
view.backgroundColor = [UIColor lightGrayColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, view.bounds.size.width, 30);
button.tag = 101+section;
button.backgroundColor = [UIColor yellowColor];
if (_sectionStatus[section] != 0) {
[button setTitle:[NSString stringWithFormat:@"%C_%@",(unichar)('A'+section),@"展开中"] forState:UIControlStateNormal];
}else{
[button setTitle:[NSString stringWithFormat:@"%C_%@",(unichar)('A'+section),@"关闭中"] forState:UIControlStateNormal];
}
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:button];
return view;
}
这里没有做相应分装,只是提供思路给大家
下面是点击分区头视图的相应和实现
- (void)btnClick:(UIButton *)button {
NSInteger section = button.tag - 101;
//跟原来状态 取反
_sectionStatus[section] = !_sectionStatus[section];
//只刷新指定分区
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
}
_sectionStatus[section] = !_sectionStatus[section];
上面是取反的,同时下面的是刷新指定的分区,记得不要去刷新整个表格,这样做的话,会很耗费其性能
大家看到这里估计都明白了吧,是不是很简单呢?
小结
最后笔者要说一下,在做次功能的时候,遇到了一个坑,因为笔者的公司要求,项目里所有的本地图片都是SVG的,很耗性能,所以在笔者点击展开分区时,就会项目闪退,因为就是因为频繁加载SVG图片。最后笔者把加载SVG的代码放到了awakeFromNib方法中,当然了,有时候也是解决不了耗性能问题,建议还是使用PNG。
源代码
本篇文章对应的源代码下载地址:
https://github.com/WSmalan/-QQ-