Tig*_*ing 19 iphone objective-c uitableview ios
我这里有一个简单的示例项目:
http://dl.dropbox.com/u/7834263/ExpandingCells.zip
在这个项目中,UITableView有一个自定义的UITableViewCell.在每个单元格中有3个包含标签的UIViews.
目标是在敲击时扩展单元格,然后在再次敲击时将其折叠.单元格本身必须更改其高度以显示子视图.插入或删除行是不可接受的.
演示项目几乎按预期工作.事实上,在iOS 4.3中,它的工作非常完美.然而,在iOS 5下,当行崩溃时,先前的单元格神奇地消失.
要重新创建问题,请在iOS 5的模拟器或设备中运行项目,然后点击第一个单元格以展开它.然后再次点击该单元格以折叠它.最后,直接点击它下面的单元格.前一个消失了.
继续点击该部分中的每个单元格将导致所有单元格消失,直到整个部分缺失的位置.
我也尝试使用reloadData而不是当前的设置,但这会破坏动画并且感觉有点像黑客.reloadRowsAtIndexPaths应该可以工作,但问题是为什么不呢?
查看下面发生的事情的图像:
表格出现:
细胞扩展:
细胞塌陷:
细胞消失(当敲击下面的细胞时):
不断重复,直到整个部分消失:
编辑: 覆盖alpha是一个黑客,但有效.这是另一个"黑客"修复它,但为什么它修复它?
JVViewController.m第125行:
if( previousIndexPath_ != nil )
{
if( [previousIndexPath_ compare:indexPath] == NSOrderedSame ) currentCellSameAsPreviousCell = YES;
JVCell *previousCell = (JVCell*)[self cellForIndexPath:previousIndexPath_];
BOOL expanded = [previousCell expanded];
if( expanded )
{
[previousCell setExpanded:NO];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
else if( currentCellSameAsPreviousCell )
{
[previousCell setExpanded:YES];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
//[indicesToReload addObject:[previousIndexPath_ copy]];
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
对演示项目做了一些小改动,值得检查并查看JVViewController didSelectRowAtIndexPath方法.
小智 21
您的问题出在setExpanded:在JVCell.m中,您正在直接编辑该方法中目标单元格的框架.
- (void)setExpanded:(BOOL)expanded
{
expanded_ = expanded;
CGFloat newHeight = heightCollapsed_;
if( expanded_ ) newHeight = heightExpanded_;
CGRect frame = self.frame;
frame.size.height = newHeight;
self.frame = frame;
}
Run Code Online (Sandbox Code Playgroud)
将其更新为:
- (void)setExpanded:(BOOL)expanded
{
expanded_ = expanded;
}
Run Code Online (Sandbox Code Playgroud)
然后删除-reloadRowsAtIndexPaths:withRowAnimation:
对JVViewController.m的第163行的调用,它将按预期动画.
-reloadRowsAtIndexPaths:withRowAnimation:
期望为提供的indexPaths返回不同的单元格.由于您只调整尺寸-beginUpdates
和-endUpdates
足以重新布局表格视图单元.
Den*_*cik 10
可能是我错过了一点,但为什么不用你:
UITableViewRowAnimationNone
我的意思是代替:
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationAutomatic];
Run Code Online (Sandbox Code Playgroud)
使用
[tableView reloadRowsAtIndexPaths:indicesToReload withRowAnimation:UITableViewRowAnimationNone];
Run Code Online (Sandbox Code Playgroud)
要为tableView的高度更改设置动画,只需调用即可.
[tableView beginUpdates];
[tableView endUpdates];
Run Code Online (Sandbox Code Playgroud)
不要调用reloadRowsAtIndexPaths:
请参阅选中时,是否可以在UITableViewCell上设置高度更改动画?
淡出的单元格是不改变大小的前一个单元格.作为国家的文件reloadRowsAtIndexPaths:withRowAnimation:
:
该表动画化了新单元格,因为它为旧行设置了动画.
会发生什么是不透明度设置为1然后立即设置为0,因此淡出.
如果先前和新单元格都改变了大小,那么它按预期工作.这是因为开始/结束更新会注意到高度的变化,并在那些覆盖那些单元格的单元格上创建新的动画reloadRowsAtIndexPaths:withRowAnimation:
.
您的问题是由于在reloadRowsAtIndexPaths:withRowAnimation:
用于加载新单元格时滥用单元格的大小.
但你根本不需要reloadRowsAtIndexPaths:withRowAnimation:
.只需更改单元格的展开状态并执行开始/结束更新.这将为您处理所有动画.
作为旁注,我发现蓝色选择有点烦人,在JVCell中将selectedBackgroundView设置为与backgroundView相同的图像(或创建具有所选单元格的正确外观的新图像).
编辑:
将添加语句previousIndexPath_
来indicesToReload
if语句(以线132),这样,如果前一小区扩大,需要调整其大小只添加.
if( expanded ) {
[previousCell setExpanded:NO];
[indicesToReload addObject:[previousIndexPath_ copy]];
}
Run Code Online (Sandbox Code Playgroud)
这消除了先前折叠的单元格将消失的情况.
另一种选择是previousIndexPath_
在当前单元格折叠时设置为nil,仅在单元格展开时设置为nil.
这仍然感觉像是一个黑客.同时执行reloadRows和开始/结束更新会导致tableView重新加载所有内容两次,但似乎都需要正确设置动画.我想如果表格不是太大,这不会是性能问题.