UITableView实现QQ好友列表实战(动态插入删除Cell)
实现选择
网上大部分的教程,都是基于修改section的hearderView来实现的,但是看QQ的好友列表,style是grouped,显然不是使用section的header来处理。使用section的hearderView来实现的,十分简单,网上也有很多源码和教程,只要刷新一下dataSource然后调用就可以了。不在本次讨论的范围之内。
- (void)reloadSections:(NSIndexSet *)sections
这次我直接使用grouped的cell来做父cell,点击后展开相应的子cell,还有动画特效。(目测QQ好友列表没有使用动画特效,可能是因为好友列表过于大,内存占用问题或者是用户体验问题。)
封装测试数据
使用FMDB(或者CoreData)从objc中国获取主issue作为父级cell,文章作为subCell,具体获取使用python和BeautifulSoup,不在本次的讨论范围之内,需要的可以查看相应的资料或者留言我,也可以在文末的项目源码里获取python代码。
具体实现分析
TableView一些相关方法介绍
delegate里和点击有关的方法如下。
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
当有点击事件发生时,运行顺序为。
- willSelect
- willDeselect
- didDeselect
- didSelect
插入删除cell的方法为
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
记得把他们放在
[table beginUpdates];
//input insert/delete code here
[table endUpdates];
逻辑分析
在didSelect的时候执行插入代码。
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationTop];
[tableView endUpdates];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
其中的indexArray需要动态计算。类似这样。
NSMutableArray* indexArray = [NSMutableArray array];
for (int i=1; i<=masterModel.subIuuses.count; i++) {
NSIndexPath* path = [NSIndexPath indexPathForRow:i+indexPath.row inSection:indexPath.section];
[indexArray addObject:path];
}
可以实现这样的效果。
问题分析
看起来没有什么问题。 但是当点击的是展开的cell下方的cell时,indexPath就会出现问题。像下面这样。
我要点击的是2x,但是实际上点击的却是4x,问题出在哪里?看这个图片就会发现问题,原来还是那几个方法的执行顺序问题。 在执行的时候,先执行didDeselect里面的代码,导致插入的cell被删除,indexPath变化,然后再didSelect,当然选中的不是我们想要选中的那个cell了。
解决方案
如下图。
只要willSelect的时候return一个新的indexPath即可,这个indexPath通过计算得出。下面是我的willSelect里的实现代码。
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell && [cell isMemberOfClass:[SIMMasterTableViewCell class]]) {
//点击masterCell
if (_isShowIssues) {
//展开状态
if(indexPath.row>_lastSelectMatserIndexPath.row)
return [NSIndexPath indexPathForRow:indexPath.row-_lastModelIssuesCount inSection:indexPath.section];
else
return indexPath;
}
return indexPath;
}
else if(cell)
{
_isSelectSubCell = YES;
return indexPath;
//点击到uitableviewcell
}
return indexPath;
}
最后放上一张效果图。
项目源码:https://github.com/XFerris/SIMObjc
- 2017奇葩机器人大盘点:Sophia想生孩子,Atlas后空翻,贝佐斯骑高达
- silverlight:分享一个不错的自定义布局CollectionFlow(可用于制作相册的哦!)
- 无法取得ConnectionSettings的问题
- DataTable,List去重复记录的方法
- Uploadify的一点总结
- 自动驾驶时代,中国移动要以怎样的姿势进入?
- JQuery中文日期控件
- Silverlight中的帧
- 窗口自动弹出浏览器显示广告的问题
- Instagram 开源用于 Python 3的MonkeyType 工具
- 拼凑了几个自定义的Panel(包括FishEyePanel,WrapPanel等几个常用的布局)
- jquery获取父级一级节点的序号
- Docker容器学习梳理--基础知识(2)
- Blend生成的TransformGroup如何引用?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- GridSearchCV (scikit learn) 确定超参数
- 10k+点赞的SpringBoot后台管理系统竟然出了详细教程!爱了!
- 数据库备份和恢复
- 在jupyter里面运行conda虚拟环境的R
- 重新夺回对 /etc/resolv.conf 的控制权
- plsql
- 打卡群2刷题总结1008——环形链表
- Oracle数据库的对象
- 打卡群刷题总结1008——加油站
- 打卡群刷题总结1005——跳跃游戏
- 真是活久见,在 Minecraft 的虚拟游戏里竟然还能管理 Kubernetes!
- 打卡群2刷题总结1007——反转链表
- 打卡群2刷题总结1001——两数之和 II - 输入有序数组
- 复杂一点的SQL语句
- PL/SQL Developer连接本地Oracle 11g 64位数据库