UIViewController 交互式过渡 - 取消交互式关闭时呈现的视图消失
Posted
技术标签:
【中文标题】UIViewController 交互式过渡 - 取消交互式关闭时呈现的视图消失【英文标题】:UIViewController interactive transition - Presented view disappears when interactive dismiss is canceled 【发布时间】:2019-01-09 18:58:03 【问题描述】:我有一个演示应用程序,我试图在其中模仿邮件应用程序“新消息”交互式转换 - 您可以向下拖动以关闭,但如果您没有拖得足够远,视图会弹回并且转换是取消。我能够在我的演示应用程序中复制过渡和交互性,但是我注意到当取消过渡被取消时,呈现的视图控制器被动画回原位,然后消失。这是它的样子:
我最好的猜测是转换上下文的容器视图由于某种原因被删除了,因为我向其中添加了呈现的视图控制器的视图。这是UIViewControllerAnimatedTransitioning
对象中的演示和关闭代码:
显示过渡
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
guard let fromVC = transitionContext.viewController(forKey: .from),
let toVC = transitionContext.viewController(forKey: .to)
else
return
let containerView = transitionContext.containerView
let finalFrame = transitionContext.finalFrame(for: toVC)
let duration = transitionDuration(using: transitionContext)
let topSafeAreaSpace = fromVC.view.safeAreaInsets.top // using fromVC safe area since it's on screen and has correct insets
let topGap: CGFloat = topSafeAreaSpace + 20
containerView.addSubview(toVC.view)
toVC.view.frame = CGRect(x: 0,
y: containerView.frame.height,
width: toVC.view.frame.width,
height: toVC.view.frame.height - 30)
UIView.animate(withDuration: duration, animations:
toVC.view.frame = CGRect(x: finalFrame.minX,
y: finalFrame.minY + topGap,
width: finalFrame.width,
height: finalFrame.height - topGap)
let sideGap: CGFloat = 20
fromVC.view.frame = CGRect(x: sideGap,
y: topSafeAreaSpace,
width: fromVC.view.frame.width - 2 * sideGap,
height: fromVC.view.frame.height - 2 * topSafeAreaSpace)
fromVC.view.layer.cornerRadius = 10
fromVC.view.layoutIfNeeded()
) _ in
transitionContext.completeTransition(true)
关闭过渡
func animateTransition(using transitionContext: UIViewControllerContextTransitioning)
guard let fromVC = transitionContext.viewController(forKey: .from),
let toVC = transitionContext.viewController(forKey: .to)
else
return
let finalFrame = transitionContext.finalFrame(for: toVC)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations:
toVC.view.frame = finalFrame
fromVC.view.frame = CGRect(x: fromVC.view.frame.minX,
y: finalFrame.height,
width: fromVC.view.frame.width,
height: fromVC.view.frame.height)
toVC.view.layer.cornerRadius = 0
toVC.view.layoutIfNeeded()
) _ in
transitionContext.completeTransition(true)
这是UIPercentDrivenInteractiveTransition
对象中的代码:
func handleGesture(_ gesture: UIPanGestureRecognizer)
#warning("need to use superview?")
let translation = gesture.translation(in: gesture.view)
var progress = translation.y / 400
progress = min(1, max(0, progress)) // constraining value between 1 and 0
switch gesture.state
case .began:
interactionInProgress = true
viewController.dismiss(animated: true, completion: nil)
case .changed:
shouldCompleteTransition = progress > 0.5
update(progress)
case .cancelled:
interactionInProgress = false
cancel()
case .ended:
interactionInProgress = false
if shouldCompleteTransition
finish()
else
cancel()
default:
break
任何帮助将不胜感激。值得注意的是,我使用了这个 Ray Wenderlich 教程作为参考 - https://www.raywenderlich.com/322-custom-uiviewcontroller-transitions-getting-started 然而,在他们使用图像快照为过渡设置动画的地方,我使用了视图控制器的视图。
【问题讨论】:
您是否尝试过将 false 传递给 transitionContext.completeTransition(_:)?根据文档,“如果到呈现的视图控制器的转换成功完成,则为 true,如果仍在显示原始视图控制器,则为 false。” developer.apple.com/documentation/uikit/… 哇,我的疏忽了。谢谢@Dare! 【参考方案1】:感谢@Dare 的评论,我意识到所需要的只是对关闭动画完成块的小更新:
// before - broken
transitionContext.completeTransition(true)
// after - WORKING!
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
【讨论】:
以上是关于UIViewController 交互式过渡 - 取消交互式关闭时呈现的视图消失的主要内容,如果未能解决你的问题,请参考以下文章
UIPageViewController 从子 UIViewController 上的控制过渡