所以我有一个非常简单的任务:为要显示的视图设置动画(高度从零到全高),然后它必须动画消失(折叠,高度变为零)。它看起来像这样:
sys
实现非常简单:我们为视图提供固定的高度约束,然后将其设置为0-> fullHeight,fullHeight-> 0。
UIButton
问题是通知中包含的NSTimer
没有收到任何触摸,因为通知的高度设置为0。
我想,另一种方法是使用dispatch_after
或DebugTree
,但这会让事情变得更复杂,我不希望这样。
问题是:我可以使用当前的方法保留用户交互吗?
答案 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)
}