Интерактивный переход UIViewController. Представленное представление исчезает при отмене интерактивного закрытия.
У меня есть демонстрационное приложение, в котором я пытаюсь имитировать интерактивный переход почтового приложения "новое сообщение". Вот как выглядит почтовый переход:
Обратите внимание, как вы можете перетащить вниз, чтобы отклонить, но если вы не перетаскиваете достаточно далеко, представление снова поднимается, и переход отменяется. Мне удалось продублировать переход и интерактивность в моем демонстрационном приложении, но я заметил, что когда отменяется переход отклонения, представленный контроллер представления возвращается на свое место, а затем исчезает. Вот как это выглядит:
Мое лучшее предположение состоит в том, что контейнерное представление контекста перехода по какой-то причине удаляется, так как я добавил к нему представленное представление контроллера представления. Вот презентация и отклонение кода внутри 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
}
}
Любая помощь будет принята с благодарностью. Стоит отметить, что я использовал этот учебник Рэя Вендерлиха как справку - https://www.raywenderlich.com/322-custom-uiviewcontroller-transitions-getting-started Однако там, где они использовали снимки изображения для анимации перехода, я использую вид взгляды контроллера.
1 ответ
Благодаря комментарию @Dare, я понял, что все, что нужно, это небольшое обновление блока завершения анимации dismiss:
// before - broken
transitionContext.completeTransition(true)
// after - WORKING!
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)