自动布局:在保持用户交互的同时将动画高度设置为零

时间:2016-07-13 22:48:13

标签: ios swift autolayout core-animation uiviewanimation

所以我有一个非常简单的任务:为要显示的视图设置动画(高度从零到全高),然后它必须动画消失(折叠,高度变为零)。它看起来像这样: sys

实现非常简单:我们为视图提供固定的高度约束,然后将其设置为0-> fullHeight,fullHeight-> 0。

UIButton

问题是通知中包含的NSTimer没有收到任何触摸,因为通知的高度设置为0。 我想,另一种方法是使用dispatch_afterDebugTree,但这会让事情变得更复杂,我不希望这样。

问题是:我可以使用当前的方法保留用户交互吗?

2 个答案:

答案 0 :(得分:1)

你是对的。一旦您调用angularjs,动画就会更新按钮框架的模型值,因此即使您的按钮仍然在屏幕上,它也只响应屏幕外区域的命中。你想要的是在按钮的表示层上进行点击测试,它将具有按钮在飞行途中的帧的值。

一个选项是子类化UIButton并覆盖animateWithDuration,如:

hitTest

这是Apple在this video.

中的建议

另一个建议here,是覆盖视图控制器中的override func hitTest(point: CGPoint, withEvent event: UIEvent!) -> UIView! { let superviewPoint = convertPoint(point, toView: superview) let point = layer.presentationLayer.convertPoint(superviewPoint, fromLayer: superview.layer) return super.hitTest(point, withEvent: event) } touchesEnded,并明确调用按钮touchesBegan上的hitTest,如下所示:

presentationLayer

这样做的缺点是你的按钮在触地时没有突出显示。

要使这些工作正常,您需要在动画上启用 override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { guard let touch = touches.first else{ return } let point = touch.locationInView(self.notificationView) if ((self.button.layer.presentationLayer()?.hitTest(point)) != nil) { // We're touching where the button is presented, so call your action self.buttonPress(self.button) } } 选项,这是您已经在做的。

答案 1 :(得分:0)

另一种选择是使用Grand Central Dispatch添加3秒延迟,而不是在动画中指定它:

notificationView.heightConstraint.constant = intrinsicHeight
UIView.animateWithDuration(0.25, animations: {
    view.layoutIfNeeded()
}) { (finished) in
    guard finished else { return }
    notificationView.heightConstraint.constant = 0
    delay(3) {
        UIView.animateWithDuration(0.25, delay: 0, options: .AllowUserInteraction, animations: {
            notificationView.superview!.layoutIfNeeded()
        }, completion: nil)
    }
}

其中delay是辅助函数,定义为:

func delay(delay:NSTimeInterval, _ f:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), f)
}