UITableViewCell
识别出水龙头时,我会为它的高度设置动画。在iOS 9及以下版本中,此动画很流畅,并且没有问题。在iOS 10 Beta中,动画过程中出现了令人讨厌的跳跃。有没有办法来解决这个问题?
这是代码的基本示例。
- (void)cellTapped {
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.shouldExpandCell ? 200.0f : 100.0f;
}
编辑:9/8/16
GM中仍然存在该问题。经过更多调试后,我发现问题与单元格立即跳至新高度有关,然后将使相关单元格偏移动画。这意味着CGRect
依赖于单元格底部的任何基于动画的动画都将不起作用。
例如,如果我将视图限制在单元格底部,它将跳转。该解决方案将涉及到一个具有动态常数的顶部约束。或想出另一种方法来定位您的视图,然后再将其与底部相关。
更好的解决方案:
问题在于何时UITableView
更改单元格的高度,最有可能从-beginUpdates
和更改-endUpdates
。到iOS 10之前对细胞的动画会发生两者的size
和origin
。现在,在iOS 10 GM中,单元将立即更改为新的高度,然后将其设置为正确的偏移量。
解决方案非常简单,有约束条件。创建一个导向约束,该约束将更新其高度并具有其他需要约束到单元格底部的视图,现在已约束到该导向。
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
UIView *heightGuide = [[UIView alloc] init];
heightGuide.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:heightGuide];
[heightGuide addConstraint:({
self.heightGuideConstraint = [NSLayoutConstraint constraintWithItem:heightGuide attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:0.0f];
})];
[self.contentView addConstraint:({
[NSLayoutConstraint constraintWithItem:heightGuide attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f];
})];
UIView *anotherView = [[UIView alloc] init];
anotherView.translatesAutoresizingMaskIntoConstraints = NO;
anotherView.backgroundColor = [UIColor redColor];
[self.contentView addSubview:anotherView];
[anotherView addConstraint:({
[NSLayoutConstraint constraintWithItem:anotherView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:20.0f];
})];
[self.contentView addConstraint:({
[NSLayoutConstraint constraintWithItem:anotherView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:0.0f];
})];
[self.contentView addConstraint:({
// This is our constraint that used to be attached to self.contentView
[NSLayoutConstraint constraintWithItem:anotherView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:heightGuide attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f];
})];
[self.contentView addConstraint:({
[NSLayoutConstraint constraintWithItem:anotherView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeRight multiplier:1.0f constant:0.0f];
})];
}
return self;
}
然后在需要时更新导板高度。
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
if (self.window) {
[UIView animateWithDuration:0.3 animations:^{
self.heightGuideConstraint.constant = frame.size.height;
[self.contentView layoutIfNeeded];
}];
} else {
self.heightGuideConstraint.constant = frame.size.height;
}
}
请注意,放入更新指南-setFrame:
可能不是最佳选择。到目前为止,我只构建了此演示代码来创建解决方案。使用最终解决方案完成代码更新后,如果我找到放置它的更好位置,我将进行编辑。
原始答案:
随着iOS 10 Beta即将完成,希望此问题将在下一版本中得到解决。还有一个开放的错误报告。
我的解决方案涉及放到该图层的CAAnimation
。这将检测高度的变化并自动进行动画处理,就像使用CALayer
取消链接到一样UIView
。
第一步是调整当图层检测到更改时发生的情况。此代码必须在视图的子类中。该视图必须是您的的子视图tableViewCell.contentView
。在代码中,我们检查视图的图层的actions属性是否具有动画的关键点。如果不是,那就叫超级。
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
return [layer.actions objectForKey:event] ?: [super actionForLayer:layer forKey:event];
}
接下来,您要将动画添加到actions属性。您可能会在视图位于窗口上并布局后,发现最好应用此代码。事先应用它可能会导致视图移动到窗口时产生动画。
- (void)didMoveToWindow {
[super didMoveToWindow];
if (self.window) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
self.layer.actions = @{animation.keyPath:animation};
}
}
就是这样!无需申请的animation.duration
,因为表视图的-beginUpdates
和-endUpdates
覆盖它。通常,如果您将此技巧用作应用动画的便捷方式,则需要添加animation.duration
,也许还要添加animation.timingFunction
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句