iOS tableview中 利用系统自带的sectionIndex
有些时候满足不了业务需求
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return XXXX;
}
所以我们大部分时间需要自定义tableview的sectionIndex导航
最下面有 demo地址见评论, 建议demo结合文章来学习
最终效果
example.gif思路
其实这种思路不难, 以我gif为例
主页面的城市列表为tableview
, 右侧的字母导航, 也为一个tableview
, 当然用for 建立 多个button
或者 Label + 手势
等也行, 但是适用于无背景, 如果你们的UI设计师设计了点击背景, 那么这种tableview
更适合于刷新背景变化。
难点
建立2个tableview
肯定没问题, 我这边建议右侧tableview
用一个额外的UIView
来处理, 不然放在一个UIView
中要分开单出处理。
难点一
点击右侧 字母tableview
要跳转对应城市tableview
中section
, 我这边是代理处理, 当然用通知
或者block
也可以
/**
*代理方法
*selindex: 传入参数为当前选择的下标
*字母的数组位置 = 城市section位置
*/
- (void)addressIndexSelect:(NSInteger)selindex {
self.scrollBool = false;
// 弹出一个当前选择的Label
UILabel *lab = [[UILabel alloc] initWithFrame: CGRectMake(SCREEN_WIDTH - 100, CGRectGetMaxY(self.addIndexView.frame) - 190, 48, 48)];
lab.textColor = [UIColor whiteColor];
lab.textAlignment = 1;
lab.font = [UIFont boldSystemFontOfSize:25];
lab.backgroundColor = [UIColor colorWithRed:225/ 255.0 green:225/255.0 blue:225/255.0 alpha:1];
lab.layer.masksToBounds = YES;
lab.layer.cornerRadius = 24;
lab.text = self.cityWordArr[selindex];
[self.view addSubview:lab];
self.kLab.hidden = YES;
// 关键代码`tableview`跳转指定section
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:selindex] atScrollPosition:UITableViewScrollPositionTop animated:NO];
self.nowScrollIndex = selindex;
// 动画消失当前字母选择Label
[UIView animateWithDuration:0.7 animations:^{
lab.alpha = 0;
} completion:^(BOOL finished) {
[lab removeFromSuperview];
self.scrollBool = true;
}];
}
关键代码tableview
跳转
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:XXX] atScrollPosition:UITableViewScrollPositionTop animated:NO];
难点二
滑动城市tableview
对应字母tableview
变化
主要是根据滑动当前位置, 判断当前在哪个区间, 从而判断, 选中哪个字母, 刷新字母tableview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.scrollBool) {
CGFloat statusH = self.view.window.windowScene.statusBarManager.statusBarFrame.size.height;
CGFloat navH = self.navigationController.navigationBar.frame.size.height;
CGFloat d = statusH + navH + 10.f;
for(int i = 1; i < self.cityWordArr.count; i++){
CGFloat bottomCellOffset1 = [self.tableView rectForSection:i - 1].origin.y - d;
CGFloat bottomCellOffset2 = [self.tableView rectForSection:i].origin.y - d;
if (scrollView.contentOffset.y < bottomCellOffset2 && scrollView.contentOffset.y >= bottomCellOffset1) {
self.addIndexView.selWordIndex = i - 1;
}else if (i == self.cityWordArr.count - 1 && scrollView.contentOffset.y >= bottomCellOffset2) {
self.addIndexView.selWordIndex = self.cityWordArr.count - 1;
}
if (self.nowScrollIndex != self.addIndexView.selWordIndex) {
[self.addIndexView.tableV reloadData];
self.nowScrollIndex = self.addIndexView.selWordIndex;
break;
}
}
}
}
(PS: 这里用for来处理, 虽然能实现, 但是不太友好, 日后会在更新版本中更换)
难点三
可以在字母tableview
滑动改变字母, 最后选择。其实这个功能我也不太想加, 如果自身无这个需求, 忽略即可。
添加滑动手势 UIPanGestureRecognizer
-
UIGestureRecognizerStateChanged
: 滑动改变时候触发, 只改变Label文字 -
UIGestureRecognizerStateEnded
: 滑动结束时候触发, 跳转指定section
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[self addGestureRecognizer:pan];
- (void)panAction:(UIGestureRecognizer *)sender {
if (self.dataArr.count != 0){
CGPoint point = [sender locationInView:self];
if (sender.state == UIGestureRecognizerStateChanged) {
self.selWordIndex = floor(point.y / (self.dataArr.count));
if (self.selWordIndex < 0){
self.selWordIndex = 0;
}else if (self.selWordIndex > self.dataArr.count - 1){
self.selWordIndex = self.dataArr.count - 1;
}
[self.delegate addressIndexScrollWord: self.selWordIndex];
[self.tableV reloadData];
}else if (sender.state == UIGestureRecognizerStateEnded) {
[self.delegate addressIndexSelect:self.selWordIndex];
}
}
}
网友评论