可展开的UITableView (附源码)

本文转载至 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.     
  21.     id<ExtensibleTableViewDelegate> delegate_extend;
  22. }
  23. @property(nonatomic,retain)id delegate_extend;
  24. @property(nonatomic,retain)NSIndexPath *currentIndexPath;
  25. //将indexPath对应的row展开
  26. - (void)extendCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated goToTop:(BOOL)goToTop;
  27. //将展开的cell收起
  28. - (void)shrinkCellWithAnimated:(BOOL)animated;
  29. //查看传来的索引和当前被选中索引是否相同
  30. - (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath;
  31. @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.     
  43.     //若当前选中的行和入参的选中行不相同,说明用户点击的不是已经展开的cell
  44.     if(![self isEqualToSelectedIndexPath:indexPath])
  45.     {
  46.         //被选中的行的索引
  47.         [array1 addObject:indexPath];
  48.     }
  49.     
  50.     //将当前被选中的索引重新赋值
  51.     currentIndexPath = indexPath;
  52.     
  53.     if(animated)
  54.     {
  55.         [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];
  56.     }
  57.     else
  58.     {
  59.         [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationNone];
  60.     }
  61.     if(goToTop)
  62.     {
  63.         //tableview滚动到新选中的行的高度
  64.         [self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
  65.     }
  66. }
  67. //将展开的cell收起
  68. - (void)shrinkCellWithAnimated:(BOOL)animated
  69. {
  70.     //要刷新的index的集合
  71.     NSMutableArray *array1 = [[NSMutableArray alloc]init];
  72.     
  73.     if(currentIndexPath)
  74.     {
  75.         //当前展开的cell的索引
  76.         [array1 addObject:currentIndexPath];
  77.         //将当前展开的cell的索引设为空
  78.         currentIndexPath = nil;
  79.         [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];    
  80.     }
  81.     
  82. }
  83. //查看传来的索引和当前被选中索引是否相同
  84. - (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath
  85. {
  86.     if(currentIndexPath)
  87.     {
  88.         return ([currentIndexPath row] == [indexPath row]) && ([currentIndexPath section] == [indexPath section]);
  89.     }
  90.     return NO;
  91. }
  92. /*
  93. 重写了这个方法,却无效,因为这个方法总在didSelect之前调用,很奇怪。因为无法重写该方法,所以ExtensibleTableView不算完善,因为还有额外的代码需要在heightForRowAtIndexPath和cellForRowAtIndexPath中。哪个找到完善的方法后希望可以与qq82934162联系或者在http://borissun.iteye.com来留言
  94. */
  95. //- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
  96. //{
  97. //    if([currentIndexPath row] == [indexPath row])
  98. //    {
  99. //        return [self.delegate_extend tableView:self extendedCellForRowAtIndexPath:indexPath];
  100. //    }
  101. //    return [super cellForRowAtIndexPath:indexPath];
  102. //}
  103. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  104. {
  105.     if([currentIndexPath row] == [indexPath row])
  106.     {
  107.         return [self.delegate_extend tableView:self extendedHeightForRowAtIndexPath:indexPath];
  108.     }
  109.     return [super rowHeight];
  110. }
  111. @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) 

原文地址:https://www.cnblogs.com/Camier-myNiuer/p/3821786.html