强制调用 UIView animateWithDuration 完成块
Posted
技术标签:
【中文标题】强制调用 UIView animateWithDuration 完成块【英文标题】:Force UIView animateWithDuration completion block to be called 【发布时间】:2017-02-14 19:17:56 【问题描述】:我有两个重叠的动画,由于我设置方法的方式,导致第二个不触发。我在方法的开头有这样的检查:
- (void)animateHidden:(BOOL)hidden duration:(CGFloat)seconds delay:(CGFloat)delay options:(UIViewAnimationOptions)options disableUserInteraction:(BOOL)disableUserInteraction
if (self.hidden == hidden)
return;
然后,再往下,我的动画块看起来像这样:
__weak UIView *weakSelf = self;
[UIView animateWithDuration:seconds delay:delay options:options animations:^
weakSelf.alpha = hidden ? 0 : 1;
completion:^(BOOL finished)
// Return user interaction to previous state
if (disableUserInteraction)
weakSelf.userInteractionEnabled = userInteractionEnabled;
weakSelf.hidden = hidden;
];
两个动画在同一个视图上启动,一个在服务调用之前,一个在服务调用之后。如果服务调用发生得足够快以至于视图仍在动画中,weakSelf.hidden = hidden;
将永远不会被调用,并且第二个动画将退出,因为hidden
的值没有及时更新。
无论如何我可以强制调用animation
块上的完成块吗?在进行检查之前,我需要更新我的 hidden
属性,但找不到完成此操作的方法。
不幸的是,致电[self.layer removeAllAnimations]
似乎不起作用。
【问题讨论】:
不确定您在这些方法中还可以做什么,但是...如果不使用您的hidden
属性/变量,而是检查.alpha
值,它对您有用吗?这会告诉你动画是否完成。
无论如何都应该调用完成块。你可以做什么?最简单/最快的方法是制作标志并检查是否已经完成。
@DonMag 问题在于,当我们调用此方法时,视图最初可能已隐藏,alpha
为 1,因此检查与对应的 alpha
值hidden
值不适用于所有视图。
【参考方案1】:
你可以用CABasicAnimation
代替UIView
动画,这样会更准确的解决问题。
你可以像这样使用它:
CABasicAnimation* opacityZero= [CABasicAnimation animationWithKeyPath:@"opacity"];
[opacityZero setToValue:[NSNumber numberWithFloat:0.0]];
[opacityZero setDuration:duration];
[[self layer] addAnimation:opacityZero forKey:@"opacityZero"];
当您的服务调用结束时,您可以致电[self.layer removeAllAnimations];
同样,您可以设置不透明度,并根据需要调整上述方法。
您可以找到更多信息here。
【讨论】:
【参考方案2】:以hidden
为前缀的__block
属性声明应该会有所帮助。
比如,@property (nonatomic) __block BOOL hidden;
【讨论】:
不幸的是,这是在扩展中,所以我无法添加任何存储的属性。【参考方案3】:如果您的目标是 ios 10+,请查看 UIViewPropertyAnimator https://developer.apple.com/reference/uikit/uiviewpropertyanimator?language=objc
结合 UIViewAnimating 和 UIViewImplicitlyAnimating 协议,可以对动画进行修改/中断/暂停/恢复/停止等。
基本示例(IB 中设置的按钮和视图):
- (IBAction)startTapped:(id)sender
_myAnimator = [UIViewPropertyAnimator
runningPropertyAnimatorWithDuration:3.0
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^
_theRedBox.alpha = _theRedBox.alpha > 0 ? 0 : 1;
completion:^(UIViewAnimatingPosition finalPosition)
// do stuff
];
- (IBAction)stopTapped:(id)sender
[_myAnimator stopAnimation:NO];
[_myAnimator finishAnimationAtPosition:UIViewAnimatingPositionEnd];
【讨论】:
以上是关于强制调用 UIView animateWithDuration 完成块的主要内容,如果未能解决你的问题,请参考以下文章
使用自动布局强制 UITableView 中的 UIView 填满屏幕