本文转载至 http://www.apkbus.com/forum.php?mod=viewthread&tid=137207&extra=page%3D1

由于工作需要,写了一个UITableView的子类,简单的实现了每个cell的展开和收缩的动画效果以及展开和收缩后的cell样式变化。这个效果也许你现在用不到,但是它在iOS上的效果确实很不错,也许以后你就会用到。分享给大家。给大家一个实际的效果: 
<ignore_js_op>

ExtensibleTableView.h

  1. //
  2. //  ExtensibleTableView.h
  3. //  Wow
  4. //
  5. //  Created by Boris Sun on 12-6-20.
  6. //  Copyright (c) 2012年 adsit. All rights reserved.
  7. //
  8. #import <UIKit/UIKit.h>
  9. @protocol ExtensibleTableViewDelegate <NSObject>
  10. @required
  11. //返回展开之后的cell
  12. - (UITableViewCell *)tableView:(UITableView *)tableView extendedCellForRowAtIndexPath:(NSIndexPath *)indexPath;
  13. //返回展开之后的cell的高度
  14. - (CGFloat)tableView:(UITableView *)tableView extendedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
  15. @end
  16. @interface ExtensibleTableView : UITableView
  17. {
  18. //当前被展开的索引
  19. NSIndexPath *currentIndexPath;
  20. id<ExtensibleTableViewDelegate> delegate_extend;
  21. }
  22. @property(nonatomic,retain)id delegate_extend;
  23. @property(nonatomic,retain)NSIndexPath *currentIndexPath;
  24. //将indexPath对应的row展开
  25. - (void)extendCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated goToTop:(BOOL)goToTop;
  26. //将展开的cell收起
  27. - (void)shrinkCellWithAnimated:(BOOL)animated;
  28. //查看传来的索引和当前被选中索引是否相同
  29. - (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath;
  30. @end

复制代码

ExtensibleTableView.m

  1. //
  2. //  ExtensibleTableView.m
  3. //  Wow
  4. //
  5. //  Created by Boris Sun on 12-6-20.
  6. //  Copyright (c) 2012年 adsit. All rights reserved.
  7. //
  8. #import "ExtensibleTableView.h"
  9. @implementation ExtensibleTableView
  10. @synthesize delegate_extend;
  11. @synthesize currentIndexPath;
  12. - (id)init
  13. {
  14. currentIndexPath = nil;
  15. return [super init];
  16. }
  17. //重写设置代理的方法,使为UITableView设置代理时,将子类的delegate_extend同样设置
  18. - (void)setDelegate:(id<UITableViewDelegate>)delegate
  19. {
  20. self.delegate_extend = delegate;
  21. [super setDelegate:delegate];
  22. }
  23. /*
  24. 将indexPath对应的row展开
  25. params:
  26. animated:是否要动画效果
  27. goToTop:展开后是否让到被展开的cell滚动到顶部
  28. */
  29. - (void)extendCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated goToTop:(BOOL)goToTop
  30. {
  31. NSLog(@"debug 2");
  32. //被取消选中的行的索引
  33. NSIndexPath *unselectedIndex = [NSIndexPath indexPathForRow:[currentIndexPath row] inSection:[currentIndexPath section]];
  34. //要刷新的index的集合
  35. NSMutableArray *array1 = [[NSMutableArray alloc]init];
  36. //若当前index不为空
  37. if(currentIndexPath)
  38. {
  39. //被取消选中的行的索引
  40. [array1 addObject:unselectedIndex];
  41. }
  42. //若当前选中的行和入参的选中行不相同,说明用户点击的不是已经展开的cell
  43. if(![self isEqualToSelectedIndexPath:indexPath])
  44. {
  45. //被选中的行的索引
  46. [array1 addObject:indexPath];
  47. }
  48. //将当前被选中的索引重新赋值
  49. currentIndexPath = indexPath;
  50. if(animated)
  51. {
  52. [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];
  53. }
  54. else
  55. {
  56. [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationNone];
  57. }
  58. if(goToTop)
  59. {
  60. //tableview滚动到新选中的行的高度
  61. [self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
  62. }
  63. }
  64. //将展开的cell收起
  65. - (void)shrinkCellWithAnimated:(BOOL)animated
  66. {
  67. //要刷新的index的集合
  68. NSMutableArray *array1 = [[NSMutableArray alloc]init];
  69. if(currentIndexPath)
  70. {
  71. //当前展开的cell的索引
  72. [array1 addObject:currentIndexPath];
  73. //将当前展开的cell的索引设为空
  74. currentIndexPath = nil;
  75. [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];
  76. }
  77. }
  78. //查看传来的索引和当前被选中索引是否相同
  79. - (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath
  80. {
  81. if(currentIndexPath)
  82. {
  83. return ([currentIndexPath row] == [indexPath row]) && ([currentIndexPath section] == [indexPath section]);
  84. }
  85. return NO;
  86. }
  87. /*
  88. 重写了这个方法,却无效,因为这个方法总在didSelect之前调用,很奇怪。因为无法重写该方法,所以ExtensibleTableView不算完善,因为还有额外的代码需要在heightForRowAtIndexPath和cellForRowAtIndexPath中。哪个找到完善的方法后希望可以与qq82934162联系或者在http://borissun.iteye.com来留言
  89. */
  90. //- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
  91. //{
  92. //    if([currentIndexPath row] == [indexPath row])
  93. //    {
  94. //        return [self.delegate_extend tableView:self extendedCellForRowAtIndexPath:indexPath];
  95. //    }
  96. //    return [super cellForRowAtIndexPath:indexPath];
  97. //}
  98. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  99. {
  100. if([currentIndexPath row] == [indexPath row])
  101. {
  102. return [self.delegate_extend tableView:self extendedHeightForRowAtIndexPath:indexPath];
  103. }
  104. return [super rowHeight];
  105. }
  106. @end

复制代码

将这2个文件放到proj之后,要设置delegate_extend并且实现 
//返回展开之后的cell 
- (UITableViewCell *)tableView:(UITableView *)tableView extendedCellForRowAtIndexPath:(NSIndexPath *)indexPath; 
//返回展开之后的cell的高度 
- (CGFloat)tableView:(UITableView *)tableView extendedHeightForRowAtIndexPath:(NSIndexPath *)indexPath; 
2个方法。

还有一点不合理的地方,我试着去解决,但是最终未果=。=!

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3. //若当前行被选中,则返回展开的cell
  4. if([tableView_ isEqualToSelectedIndexPath:indexPath])
  5. {
  6. return [self tableView:tableView extendedCellForRowAtIndexPath:indexPath];
  7. }
  8. ...
  9. }

复制代码

这里要先判断当前行是否被选中,若被选中则调用extendedCellForRowAtIndexPath方法。因为我试着重写UITableView的- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath方法。试图在这个方法里做上边的事情,可是这个方法总是在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法之前被调用,因此没有达到预期的目标。
<ignore_js_op> ExtensibleTableViewDemo.zip (30.88 KB, 下载次数: 53)

可展开的UITableView (附源码)的更多相关文章

  1. (原创)通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  2. 通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    原文:通用查询实现方案(可用于DDD)[附源码] -- 设计思路 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   ...

  3. PYTHON爬虫实战_垃圾佬闲鱼爬虫转转爬虫数据整合自用二手急速响应捡垃圾平台_3(附源码持续更新)

    说明 文章首发于HURUWO的博客小站,本平台做同步备份发布. 如有浏览或访问异常图片加载失败或者相关疑问可前往原博客下评论浏览. 原文链接 PYTHON爬虫实战_垃圾佬闲鱼爬虫转转爬虫数据整合自用二 ...

  4. 在网站开发中很有用的8个 jQuery 效果【附源码】

    jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...

  5. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  6. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  7. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  8. 轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)

    在网络上,交互的双方基于TCP或UDP进行通信,通信协议的格式通常分为两类:文本消息.二进制消息. 文本协议相对简单,通常使用一个特殊的标记符作为一个消息的结束. 二进制协议,通常是由消息头(Head ...

  9. jquery自定义插件结合baiduTemplate.js实现异步刷新(附源码)

    上一篇记录了BaiduTemplate模板引擎使用示例附源码,在此基础上对使用方法进行了封装 自定义插件jajaxrefresh.js 代码如下: //闭包限定命名空间 (function ($) { ...

随机推荐

  1. 更新到xcode10以后出现几个无奈的问题,谨已此篇告诫广大ioser升级请慎重

    1.第一次用xcode 10 archive的时候遇到的电脑卡死不动的问题,期间鼠标键盘通通都动不了,只能强制关机来解决,于是又进行了一次可还是遇到相同的问题,无奈之下只能等待,大约20分钟左右(20 ...

  2. TP5 多条件whereOr查询

    问题背景:最近在用ThinkPHP 5开发项目的过程中,发现根据筛选条件做or查询的时候,连贯操作不可以使用where进行条件查询了. 首先列出一个user数据表的信息: uid uname grad ...

  3. centos7.2安装tomcat8

    环境: 阿里云centos7.2 tomcat8.0.32 jdk8.131 1 上传tomcat安装包到服务器的/home(个人习惯) 2 解压安装包 [root@iZt4n6h3u4k407nni ...

  4. 交换机的MAC地址作用

    交换机的MAC地址在交换机进行数据交换时是没有作用的,因为交换机并不对转发的数据帧进行拆包重封装. 如果只是完成数据帧交换,则可以不要MAC地址(仅指二层交换机,三层交换机完成路由功能自然每个端口得有 ...

  5. 记一次kubernetes集群异常: kubelet连接apiserver超时

    Background kubernetes是master-slave结构,master node是集群的大脑, 当master node发生故障时整个集群都"out of control&q ...

  6. fs寄存器相关,PEB,TEB

    ---恢复内容开始--- FS寄存器指向:偏移 说明000 指向SEH链指针004 线程堆栈顶部008 线程堆栈底部00C SubSystemTib010 FiberData014 Arbitrary ...

  7. {dede:sql}标签的用法

    sql标签可以称得上是个万能标签了,查询数据库将其输出,这里介绍一些关于这个标签的用法: 1.用来输出统计内容,这个是不错的,举个例子,我们来统计下总共发了多少的文章,思路就是输出dede_addon ...

  8. 时间迭代和BigDecimal操作

    常规小操作的代码: import java.math.BigDecimal; import java.sql.Timestamp; import java.text.SimpleDateFormat; ...

  9. Shell脚本部分语法

    Shell中的变量   Linux Shell中的变量分为“系统变量”和“用户自定义变量”,可以通过set命令查看那系统变量 系统变量:$HOME.$PWD.$SHELL.$USER等等 显示当前sh ...

  10. Mockito图书馆

    转载:https://static.javadoc.io/org.mockito/mockito-core/2.12.0/org/mockito/Mockito.html#42 org.mockito ...