我有两个视图控制器,从第一个我用模态segue显示第二个,显示样式设置为over current context
。我也使用在过渡期间出现的模糊效果并在之后消失。
我已经创建了一个演示应用来展示过渡的样子:
此处,第二个视图控制器包含UIScrollView
,并且在其上方有一个黄色矩形,另一个是UIView
,上面有UIButton
。 UIButton
也关闭了视图控制器。另外,正如您所看到的,我已将背景颜色设置为clear
,因此可以看到模糊效果。
现在,在我的项目中,转换基本相同,除了我的视图控制器更重"。
第一个视图控制器嵌入在UINavigationController"
和UITabBarController
内部,在其上我有一个自定义分段控件
由UIView
和UIButton
s以及带有自定义单元格的UITableView
制作。
第二个视图控制器由UIScrollView
和UIView
组成(如上图所示,稍微大一点)。 view
包含UIImageView
,UILabel
和较小的UIView
,用作关闭视图的按钮。
这是我用来关闭第二个视图控制器的代码(UIScrollViewDelegate
的方法)。
extension AuthorInfoViewController: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isDragging = true
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard isDragging else {
return
}
if !isDismissingAuthorInfo && scrollView.contentOffset.y < -30.0 && dismissAnimator != nil {
authoInfoViewControllerDelegate?.authorInfoViewControllerWillDismiss()
isDismissingAuthorInfo = true
dismissAnimator?.wantsInteractiveStart = true
dismiss(animated: true, completion: nil)
return
}
if isDismissingAuthorInfo {
let progress = max(0.0, min(1.0, ((-scrollView.contentOffset.y) - 30) / 90.0))
dismissAnimator?.update(progress)
}
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let progress = max(0.0, min(1.0, ((-scrollView.contentOffset.y) - 30) / 90.0))
if progress > 0.5 {
dismissAnimator?.finish()
} else {
dismissAnimator?.cancel()
print("Canceled")
}
isDismissingAuthorInfo = false
isDragging = false
}
}
此处,isDismissingAuthorInfo
和isDragging
是保留的布尔值
跟踪视图是否正在消失并被拖动。 authorInfoViewControllerWillDismiss
是在符合第一个视图控制器的协议中实现的方法。该方法调用另一种方法,将模糊动画添加到自定义过渡动画师。
已编辑
动画师代码如下:
class DismissAnimator: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning {
var auxAnimationsForBlur: (()->Void)?
var auxAnimationsForTabBar: (()->Void)?
var auxAnimationsCancelForBlur: (()->Void)?
var auxAnimationsCancelForTabBar: (()->Void)?
var tabBar: UITabBar?
var blurView: UIView?
let transitionDuration = 0.75
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return transitionDuration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
transitionAnimator(using: transitionContext).startAnimation()
}
func transitionAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
let duration = transitionDuration(using: transitionContext)
let container = transitionContext.containerView
let from = transitionContext.view(forKey: .from)!
container.addSubview(from)
let animator = UIViewPropertyAnimator(duration: duration, curve: .easeOut)
animator.addAnimations({
from.transform = CGAffineTransform(translationX: 0.0, y: container.frame.size.height + 30)
}, delayFactor: 0.15)
animator.addCompletion { (position) in
switch position {
case .end:
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
self.tabBar?.isHidden = false
self.blurView?.removeFromSuperview()
default:
transitionContext.completeTransition(false)
self.auxAnimationsCancelForBlur?()
self.auxAnimationsCancelForTabBar?()
}
}
if let auxAnimationsForBlur = auxAnimationsForBlur {
animator.addAnimations(auxAnimationsForBlur)
}
if let auxAnimationsForTabBar = auxAnimationsForTabBar {
animator.addAnimations(auxAnimationsForTabBar)
}
return animator
}
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
return transitionAnimator(using:transitionContext)
}
}
在上面的代码中,auxAnimationsForBlur
用于向动画师添加模糊动画,auxAnimationsCancelForBlur
用于取消动画,auxAnimationsForTabBar
用于添加动画alpha
值tabBar
,auxAnimationsCancelForTabBar
用于取消它。
现在,问题如下:动画工作正常,但是在通过拖动第二个视图控制器多次(5-9,大约)运行它之后,在转换结束并显示第一个视图控制器之后,它只是停止响应。但是,在底部我有一个tab bar
,它可以工作。因此,当我切换到另一个选项卡并返回时,我看到第二个视图控制器和它后面的黑屏(第一个视图控制器应该在哪里)。发生这种情况时,cancel
上的UIPercentDrivenInteractiveTransition
方法会从上面的scrollViewWillEndDragging
方法调用(在控制台上我会看到打印出来的cancel
)。 cancel
UIPercentDrivenInteractiveTransition
上的interruptibleAnimator(using:)
方法是否可能导致此问题,因为当我注释掉该方法的调用时,似乎一切正常(在这种情况下,我也会注释掉)在我的动画师上调用print(Xtrain['Sex'].head().tolist())
方法,所以我失去了过渡的交互行为)?通过点击关闭按钮关闭第二个视图控制器时,我无法重现此行为,所以我认为它与拖动有关。
什么可能导致这个问题,你有什么建议解决它?我非常感谢你的帮助。