可展开的UITableView (附源码)

由于工作需要,写了一个UITableView的子类,简单的实现了每个cell的展开和收缩的动画效果以及展开和收缩后的cell样式变化。这个效果也许你现在用不到,但是它在iOS上的效果确实很不错,也许以后你就会用到。分享给大家。给大家一个实际的效果:
[img]http://dl.iteye.com/upload/attachment/0072/9698/d7df90bb-c368-3af0-b0db-89ec0f02fa62.png[/img]


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方法。试图在这个方法里做上边的事情,可是这个方法总是在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法之前被调用,因此没有达到预期的目标。
希望各位如果下载了源码,解决了这个问题的话,可以回到这里给我留言或者联系qq82934162.

以下是一个简单的demo源码:
[url]http://dl.iteye.com/topics/download/4f242bbb-8004-3352-9604-b1211b7562df[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值