[英]Auto-Layout, animation, and layers in subview
在基于约束的视图中,有几个标签(顶部),按钮(底部)和一个自定义的UIView子类(检查器),该子类由许多CALayers组成。 我试图通过删除和添加约束为视图的大小设置动画:
// self.containerWidth is a constraint instance
// from Interface Builder Outlet, which is set to
// constrain the width of the whole view.
[self.calendarContainer removeConstraint:self.containerWidth];
[UIView animateWithDuration:4.0 animations:^{
[self.calendarContainer addConstraint:
[NSLayoutConstraint constraintWithItem:self.calendarContainer
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:0
constant:700]];
[self.calendarContainer layoutIfNeeded];
}];
动画后,视图如下所示:
在动画过程中,标签(顶部)和按钮(底部)按照上面给出的持续时间平稳地移动, 但是,检查器视图在发生任何其他过渡之前非常快速地反弹到最终状态。
我怀疑有些隐含地与某些CATransaction混合在一起。
在检查器视图中,我重新排列了-layoutSubviews
中各层的-layoutSubviews
:
- (void)layoutSubviews {
[super layoutSubviews];
if (!self.layer.sublayers.count) {
[self prepareLayers];
}
int rowCount = [self rowCount];
CGFloat rowHeight = [self rowHeight];
[self.layer.sublayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CALayer *rowLayer = obj;
NSNumber *rowIndex = [rowLayer valueForKey:@"rowindex"];
if (rowIndex) {
NSUInteger rowIndexValue = rowIndex.integerValue;
if (rowIndexValue < rowCount) {
rowLayer.hidden = NO;
rowLayer.frame = CGRectMake(0, rowHeight * rowIndexValue, self.frame.size.width, rowHeight);
[rowLayer.sublayers enumerateObjectsUsingBlock:^(id obj2, NSUInteger idx2, BOOL *stop2) {
CALayer *cellLayer = obj2;
NSUInteger colIndex = [[cellLayer valueForKey:@"cellindex"] integerValue] - rowIndexValue * 7 - 1;
cellLayer.frame = CGRectMake(colIndex*self.frame.size.width/7, 0, self.frame.size.width/7, rowHeight);
}];
} else {
// hide
rowLayer.hidden = YES;
}
}
}];
}
如何纠正这些动画?
顺便说一句,最建议在哪里插入这些图层重新定位代码?
效果似乎是由层的隐式动画引起的。
以下代码可以修复所有动画不匹配的问题。
NSTimeInterval duration = 4.0;
[UIView animateWithDuration:duration animations:^{
[CATransaction begin];
[CATransaction setValue:@(duration)
forKey:kCATransactionAnimationDuration];
CAMediaTimingFunction *func = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[CATransaction setAnimationTimingFunction:func];
[self.calendarContainer removeConstraint:self.containerWidth];
[self.calendarContainer addConstraint:[NSLayoutConstraint constraintWithItem:self.calendarContainer attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0 constant:700]];
[self.calendarContainer layoutIfNeeded];
[CATransaction commit];
}];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.