使用 UINavigationController 和 UINavigationBar 时图层的 y 位置动画错误
Wrong animation of layer's y position when using a UINavigationController and UINavigationBar
我像往常一样在 viewWillAppear:
中设置和自定义 UINavigationController's
导航栏。然后我以 0.6 的时间间隔在 viewDidLoad
中触发 NSTimer
。这个计时器触发了我的动画代码。
我正在使用 Facebook 的 POP 框架,我想做的就是使用以下代码稍微改变图层的 y 位置并稍微反弹一下:
// Move object up
POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
positionAnimation.toValue = @(self.myView.frame.origin.y - 5);
positionAnimation.springBounciness = 20;
positionAnimation.velocity = @(2000);
[self.myView.layer pop_addAnimation:positionAnimation1 forKey:@"positionAnimation"];
出于某种原因,这总是会导致视图在 UINavigationBar
下方的一半位置。如果我切换到以下代码,视图将转到正确的位置:
POPSpringAnimation *frameAnimation = [POPSpringAnimation animation];
frameAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
frameAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(12, 24, 91, 116)];
[self.myView.layer pop_addAnimation:secondFrameAnimation forKey:@"frameAnimation"];
问题是,如果我尝试使用 velocity
属性 将任何反弹添加到 frameAnimation
,应用程序崩溃并且出现以下错误:
'Invalid value', reason: '2000 should be of type CGRect'
如果我将我的 positionAnimation
代码放入一个新项目中,该项目不使用带有导航栏的 UINavigationController
,则一切正常并且视图动画到正确的 y 位置.唯一的其他区别也是我当前的项目是从 nib/xib
文件加载此视图,但一切都是在新项目中以编程方式完成的。我不确定这是否与它有任何关系。
那么如何才能使用带导航栏的导航控制器,同时又能成功使用位置动画呢?
编辑:
我现在动画可以正常工作,但仍然遇到一些非常奇怪的行为。这是成功移动视图而不是将其放在 UINavigationBar
:
下方的代码
// Fade in
POPSpringAnimation *opacityAnimation = [POPSpringAnimation animation];
opacityAnimation.property = [POPAnimatableProperty propertyWithName:kPOPLayerOpacity];
opacityAnimation.toValue = @(1.0);
[self.design.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"];
// Move object up
POPSpringAnimation *positionAnimation1 = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
positionAnimation1.toValue = @(self.design.frame.origin.y - 10);
positionAnimation1.springBounciness = 15;
positionAnimation1.velocity = @(2000);
[self.design.layer pop_addAnimation:positionAnimation1 forKey:@"positionAnimation"];
[positionAnimation1 setCompletionBlock:^(POPAnimation *anim, BOOL success) {
//
NSLog(@"design frame: %@", NSStringFromCGRect(self.design.frame));
}];
这里有一些奇怪的地方。当上述动画的完成块触发时,帧记录如下:
design frame: {{12, 36}, {91, 116}}
没错。但是,如果我更改位置动画的以下行并仅切换 36
的 y 值,它再次在 UINavigationBar
:
下方的一半处结束
positionAnimation1.toValue = @(36);
那么,为什么我在使用 36 的 y 值时会得到一个糟糕的结果,为什么我使用 self.design.frame.origin.y - 10
的 y 值时它仍然有效,最终还是 36?
动画 kPOPLayerPositionY
控制图层中心位置的 y 值,而不是框架上的原点。以下应该有效:
positionAnimation1.toValue = @(36 + 116 * 0.5);
对于您之前提到的速度错误,这是因为速度参数中的组件数量必须与正在动画的 属性 中的组件数量相匹配。因此,如果您正在为 CGRect 设置动画,则需要将 CGRect 传递给 velocity,其中每个组件都是相应组件的速度。
我像往常一样在 viewWillAppear:
中设置和自定义 UINavigationController's
导航栏。然后我以 0.6 的时间间隔在 viewDidLoad
中触发 NSTimer
。这个计时器触发了我的动画代码。
我正在使用 Facebook 的 POP 框架,我想做的就是使用以下代码稍微改变图层的 y 位置并稍微反弹一下:
// Move object up
POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
positionAnimation.toValue = @(self.myView.frame.origin.y - 5);
positionAnimation.springBounciness = 20;
positionAnimation.velocity = @(2000);
[self.myView.layer pop_addAnimation:positionAnimation1 forKey:@"positionAnimation"];
出于某种原因,这总是会导致视图在 UINavigationBar
下方的一半位置。如果我切换到以下代码,视图将转到正确的位置:
POPSpringAnimation *frameAnimation = [POPSpringAnimation animation];
frameAnimation.property = [POPAnimatableProperty propertyWithName:kPOPViewFrame];
frameAnimation.toValue = [NSValue valueWithCGRect:CGRectMake(12, 24, 91, 116)];
[self.myView.layer pop_addAnimation:secondFrameAnimation forKey:@"frameAnimation"];
问题是,如果我尝试使用 velocity
属性 将任何反弹添加到 frameAnimation
,应用程序崩溃并且出现以下错误:
'Invalid value', reason: '2000 should be of type CGRect'
如果我将我的 positionAnimation
代码放入一个新项目中,该项目不使用带有导航栏的 UINavigationController
,则一切正常并且视图动画到正确的 y 位置.唯一的其他区别也是我当前的项目是从 nib/xib
文件加载此视图,但一切都是在新项目中以编程方式完成的。我不确定这是否与它有任何关系。
那么如何才能使用带导航栏的导航控制器,同时又能成功使用位置动画呢?
编辑:
我现在动画可以正常工作,但仍然遇到一些非常奇怪的行为。这是成功移动视图而不是将其放在 UINavigationBar
:
// Fade in
POPSpringAnimation *opacityAnimation = [POPSpringAnimation animation];
opacityAnimation.property = [POPAnimatableProperty propertyWithName:kPOPLayerOpacity];
opacityAnimation.toValue = @(1.0);
[self.design.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"];
// Move object up
POPSpringAnimation *positionAnimation1 = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
positionAnimation1.toValue = @(self.design.frame.origin.y - 10);
positionAnimation1.springBounciness = 15;
positionAnimation1.velocity = @(2000);
[self.design.layer pop_addAnimation:positionAnimation1 forKey:@"positionAnimation"];
[positionAnimation1 setCompletionBlock:^(POPAnimation *anim, BOOL success) {
//
NSLog(@"design frame: %@", NSStringFromCGRect(self.design.frame));
}];
这里有一些奇怪的地方。当上述动画的完成块触发时,帧记录如下:
design frame: {{12, 36}, {91, 116}}
没错。但是,如果我更改位置动画的以下行并仅切换 36
的 y 值,它再次在 UINavigationBar
:
positionAnimation1.toValue = @(36);
那么,为什么我在使用 36 的 y 值时会得到一个糟糕的结果,为什么我使用 self.design.frame.origin.y - 10
的 y 值时它仍然有效,最终还是 36?
动画 kPOPLayerPositionY
控制图层中心位置的 y 值,而不是框架上的原点。以下应该有效:
positionAnimation1.toValue = @(36 + 116 * 0.5);
对于您之前提到的速度错误,这是因为速度参数中的组件数量必须与正在动画的 属性 中的组件数量相匹配。因此,如果您正在为 CGRect 设置动画,则需要将 CGRect 传递给 velocity,其中每个组件都是相应组件的速度。