调用 deleteRowsAtIndexPaths 时,具有自动调整单元格大小的 UITableView 变得不稳定
UITableView with self sizing cells becomes jerky when calling deleteRowsAtIndexPaths
我有一个 UITable视图,其中包含自动调整单元格的大小。 Table 包含 1 个部分和一些行。我有一些行说 30,我想在 didSelectRowAtIndexPath
期间删除行。
当我删除 table 视图底部附近可用的一行(比如第 28 行)时,第 28 行之前的行改变了它们的位置,并且由于 deleteRowsAtIndexPaths
而导致动画不稳定。有关详细信息,请参阅附加的 gif。
Cells constructed with frame deletion animation
Auto Resizing cells Deletion animation
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return noOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setCellText:[NSString stringWithFormat:@"Section = %li Row = %li", indexPath.section,indexPath.row]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
noOfRows--;
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
}
这种不稳定的动画只发生在自动调整大小的单元格上,而不是用框架构造的单元格。
任何帮助将不胜感激。
编辑 1: 问题是内容偏移量和内容大小。假设 table 视图中的每个单元格的高度为 50。因此,对于 20 个单元格,内容大小约为 1000。假设设备高度为 200,宽度为 100.So,内容大小将为 100,1000 .当我滚动到 table 视图底部时,内容偏移量变为 0,800。当我现在删除一行时,内容大小将更新为 100、950,并且由于内容大小的变化,内容偏移量现在会尝试调整为新值。所以这会导致抖动。
像这样更新你的方法并尝试:
cellForRowAtIndexPath:
[cell setNeedsUpdateConstraints];
[cell layoutIfNeeded];
didSelectRowAtIndexPath:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
noOfRows--;
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
不稳定的动画是由于您的单元格高度估计不正确造成的。因此,您需要在 table 视图控制器中实现 estimatedRowHeight
并 return 保存高度。您可以将先前加载的单元格高度保存在 willDisplayCell
tableView 委托方法中作为数组中的 cell.frame.size.height
。
var estimatedHeights : [CGFloat] = []
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
if estimatedHeights.count > indexPath.row
{
return estimatedHeights[indexPath.row]
}
return 40
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
if estimatedHeights.count <= indexPath.row
{
estimatedHeights.append(cell.frame.height)
}
else
{
estimatedHeights[indexPath.row] = cell.frame.height
}
}
同时将您的删除代码放在 [tableView beginUpdates];
和 [tableView endUpdates];
中
我有一个 UITable视图,其中包含自动调整单元格的大小。 Table 包含 1 个部分和一些行。我有一些行说 30,我想在 didSelectRowAtIndexPath
期间删除行。
当我删除 table 视图底部附近可用的一行(比如第 28 行)时,第 28 行之前的行改变了它们的位置,并且由于 deleteRowsAtIndexPaths
而导致动画不稳定。有关详细信息,请参阅附加的 gif。
Cells constructed with frame deletion animation
Auto Resizing cells Deletion animation
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return noOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setCellText:[NSString stringWithFormat:@"Section = %li Row = %li", indexPath.section,indexPath.row]];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
noOfRows--;
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
}
这种不稳定的动画只发生在自动调整大小的单元格上,而不是用框架构造的单元格。 任何帮助将不胜感激。
编辑 1: 问题是内容偏移量和内容大小。假设 table 视图中的每个单元格的高度为 50。因此,对于 20 个单元格,内容大小约为 1000。假设设备高度为 200,宽度为 100.So,内容大小将为 100,1000 .当我滚动到 table 视图底部时,内容偏移量变为 0,800。当我现在删除一行时,内容大小将更新为 100、950,并且由于内容大小的变化,内容偏移量现在会尝试调整为新值。所以这会导致抖动。
像这样更新你的方法并尝试:
cellForRowAtIndexPath:
[cell setNeedsUpdateConstraints];
[cell layoutIfNeeded];
didSelectRowAtIndexPath:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
noOfRows--;
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:indexPath.row inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
不稳定的动画是由于您的单元格高度估计不正确造成的。因此,您需要在 table 视图控制器中实现 estimatedRowHeight
并 return 保存高度。您可以将先前加载的单元格高度保存在 willDisplayCell
tableView 委托方法中作为数组中的 cell.frame.size.height
。
var estimatedHeights : [CGFloat] = []
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
if estimatedHeights.count > indexPath.row
{
return estimatedHeights[indexPath.row]
}
return 40
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
if estimatedHeights.count <= indexPath.row
{
estimatedHeights.append(cell.frame.height)
}
else
{
estimatedHeights[indexPath.row] = cell.frame.height
}
}
同时将您的删除代码放在 [tableView beginUpdates];
和 [tableView endUpdates];