读书人

可铺展的UITableView (附源码)

发布时间: 2012-09-25 09:55:58 作者: rapoo

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



ExtensibleTableView.h

////  ExtensibleTableView.h//  Wow////  Created by Boris Sun on 12-6-20.//  Copyright (c) 2012年 adsit. All rights reserved.//#import <UIKit/UIKit.h>@protocol ExtensibleTableViewDelegate <NSObject>@required//返回展开之后的cell- (UITableViewCell *)tableView:(UITableView *)tableView extendedCellForRowAtIndexPath:(NSIndexPath *)indexPath;//返回展开之后的cell的高度- (CGFloat)tableView:(UITableView *)tableView extendedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;@end@interface ExtensibleTableView : UITableView{    //当前被展开的索引    NSIndexPath *currentIndexPath;        id<ExtensibleTableViewDelegate> delegate_extend;}@property(nonatomic,retain)id delegate_extend;@property(nonatomic,retain)NSIndexPath *currentIndexPath;//将indexPath对应的row展开- (void)extendCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated goToTop:(BOOL)goToTop;//将展开的cell收起- (void)shrinkCellWithAnimated:(BOOL)animated;//查看传来的索引和当前被选中索引是否相同- (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath;@end


ExtensibleTableView.m
////  ExtensibleTableView.m//  Wow////  Created by Boris Sun on 12-6-20.//  Copyright (c) 2012年 adsit. All rights reserved.//#import "ExtensibleTableView.h"@implementation ExtensibleTableView@synthesize delegate_extend;@synthesize currentIndexPath;- (id)init{    currentIndexPath = nil;    return [super init];}//重写设置代理的方法,使为UITableView设置代理时,将子类的delegate_extend同样设置- (void)setDelegate:(id<UITableViewDelegate>)delegate{    self.delegate_extend = delegate;    [super setDelegate:delegate];}/*  将indexPath对应的row展开 params:  animated:是否要动画效果 goToTop:展开后是否让到被展开的cell滚动到顶部  */- (void)extendCellAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated goToTop:(BOOL)goToTop{          NSLog(@"debug 2");    //被取消选中的行的索引    NSIndexPath *unselectedIndex = [NSIndexPath indexPathForRow:[currentIndexPath row] inSection:[currentIndexPath section]];    //要刷新的index的集合    NSMutableArray *array1 = [[NSMutableArray alloc]init];    //若当前index不为空    if(currentIndexPath)    {        //被取消选中的行的索引        [array1 addObject:unselectedIndex];    }        //若当前选中的行和入参的选中行不相同,说明用户点击的不是已经展开的cell    if(![self isEqualToSelectedIndexPath:indexPath])    {        //被选中的行的索引        [array1 addObject:indexPath];    }        //将当前被选中的索引重新赋值    currentIndexPath = indexPath;        if(animated)    {        [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];    }    else    {        [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationNone];    }    if(goToTop)    {        //tableview滚动到新选中的行的高度        [self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];    }}//将展开的cell收起- (void)shrinkCellWithAnimated:(BOOL)animated{    //要刷新的index的集合    NSMutableArray *array1 = [[NSMutableArray alloc]init];        if(currentIndexPath)    {        //当前展开的cell的索引        [array1 addObject:currentIndexPath];        //将当前展开的cell的索引设为空        currentIndexPath = nil;        [self reloadRowsAtIndexPaths:array1 withRowAnimation:UITableViewRowAnimationFade];        }    }//查看传来的索引和当前被选中索引是否相同- (BOOL)isEqualToSelectedIndexPath:(NSIndexPath *)indexPath{    if(currentIndexPath)    {        return ([currentIndexPath row] == [indexPath row]) && ([currentIndexPath section] == [indexPath section]);    }    return NO;}/*  重写了这个方法,却无效,因为这个方法总在didSelect之前调用,很奇怪。因为无法重写该方法,所以ExtensibleTableView不算完善,因为还有额外的代码需要在heightForRowAtIndexPath和cellForRowAtIndexPath中。哪个找到完善的方法后希望可以与qq82934162联系或者在http://borissun.iteye.com来留言 *///- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath//{//    if([currentIndexPath row] == [indexPath row])//    {//        return [self.delegate_extend tableView:self extendedCellForRowAtIndexPath:indexPath];//    }//    return [super cellForRowAtIndexPath:indexPath];//}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    if([currentIndexPath row] == [indexPath row])    {        return [self.delegate_extend tableView:self extendedHeightForRowAtIndexPath:indexPath];    }    return [super rowHeight];}@end

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

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

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


这里要先判断当前行是否被选中,若被选中则调用extendedCellForRowAtIndexPath方法。因为我试着重写UITableView的- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath方法。试图在这个方法里做上边的事情,可是这个方法总是在didSelect方法之前被调用,因此没有达到预期的目标。
希望各位如果下载了源码,解决了这个问题的话,可以回到这里给我留言或者联系qq82934162.

以下是一个简单的demo源码:
http://dl.iteye.com/topics/download/4f242bbb-8004-3352-9604-b1211b7562df 1 楼 thinmonkey 2012-08-28 只有想不到的,没有做不到的,楼主很牛 2 楼 wangjian1000096 前天 楼主,点击事件后第一行会抖动诶

读书人网 >移动开发

热点推荐