我在UIView上需要两个动画:
当我尝试这样做时,第二个动画在一个奇怪的位置开始,但最终位于正确的位置和大小。如何让第二个动画从第一个动画结束的相同位置开始?
#import "ViewController.h"
static const CGFloat kStartX = 100.0;
static const CGFloat kStartY = 20.0;
static const CGFloat kStartSize = 30.0;
static const CGFloat kEndCenterY = 200.0;
@interface ViewController ()
@property (nonatomic, strong) UIView *box;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.box = [[UIView alloc] initWithFrame:CGRectMake(kStartX, kStartY, kStartSize, kStartSize)];
self.box.backgroundColor = [UIColor brownColor];
[self.view addSubview:self.box];
[UIView animateWithDuration:2.0
delay:1.0
usingSpringWithDamping:1.0
initialSpringVelocity:0.0
options:0
animations:^{
self.box.transform = [self _transformForSize:50.0 centerY:kEndCenterY];
}
completion:^(BOOL finished) {
[UIView animateWithDuration:2.0
delay:1.0
usingSpringWithDamping:1.0
initialSpringVelocity:0.0
options:0
animations:^{
self.box.transform = [self _transformForSize:100.0 centerY:kEndCenterY];
}
completion:^(BOOL finished) {
}];
}];
}
- (CGAffineTransform)_transformForSize:(CGFloat)newSize centerY:(CGFloat)newCenterY
{
CGFloat newScale = newSize / kStartSize;
CGFloat startCenterY = kStartY + kStartSize / 2.0;
CGFloat deltaY = newCenterY - startCenterY;
CGAffineTransform translation = CGAffineTransformMakeTranslation(0.0, deltaY);
CGAffineTransform scaling = CGAffineTransformMakeScale(newScale, newScale);
return CGAffineTransformConcat(scaling, translation);
}
@end
有一点需要注意:我被迫使用setTransform而不是setFrame。我在我的真实代码中没有使用棕色盒子。我的真实代码是使用复杂的UIView子类,当我使用setFrame时,它不能平滑地缩放。
答案 0 :(得分:0)
这看起来像可能是一个UIKit错误,当你在现有的转换上应用转换时,UIViews如何解析它们的布局。通过在第二个完成块的最开始执行以下操作,我能够至少获得第二个动画的起始坐标:
[UIView animateWithDuration:2.0
delay:1.0
usingSpringWithDamping:1.0
initialSpringVelocity:0.0
options:0
animations:^{
self.box.transform = [self _transformForSize:50.0 centerY:kEndCenterY];
}
completion:^(BOOL finished) {
// <new code here>
CGRect newFrame = self.box.frame;
self.box.transform = CGAffineTransformIdentity;
self.box.frame = newFrame;
// </new code>
[UIView animateWithDuration:2.0
delay:1.0
usingSpringWithDamping:1.0
initialSpringVelocity:0.0
options:0
animations:^{
self.box.transform = [self _transformForSize:100.0 centerY:kEndCenterY];
}
completion:^(BOOL finished) {
}];
}];
对-_transformForSize:centerY:
使用相同的调用会导致在第二个动画中执行相同的Y平移,因此在完成所有操作后,该框在视图中的结尾比您想要的更深。
要解决此问题,您需要根据第一个动画的 end 处的框起始Y坐标而不是原始的常量Y坐标来计算deltaY:
- (CGAffineTransform)_transformForSize:(CGFloat)newSize centerY:(CGFloat)newCenterY
{
CGFloat newScale = newSize / kStartSize;
// Replace this line:
CGFloat startCenterY = kStartY + kStartSize / 2.0;
// With this one:
CGFloat startCenterY = self.box.frame.origin.y + self.box.frame.size.height / 2.0;
// </replace>
CGFloat deltaY = newCenterY - startCenterY;
CGAffineTransform translation = CGAffineTransformMakeTranslation(0.0, deltaY);
CGAffineTransform scaling = CGAffineTransformMakeScale(newScale, newScale);
return CGAffineTransformConcat(scaling, translation);
}
它应该可以解决问题。
<强>更新强>
我应该说,我认为这是&#34;技巧&#34;更多的是解决方案而不是实际的解决方案,但是框的框架和转换在动画流水线的每个阶段看起来都是正确的,所以如果有一个真正的解决方案&#34;它此刻正在躲避我。这个技巧至少可以解决您的翻译问题,因此您可以尝试更复杂的视图层次结构,看看您能获得多少。