在回答this之后,我设法将ViewControllerB
的半峰形式添加到ViewControllerA
中。但是,在示例中,ViewControllerA
只是一个红色视图。我想将其连接到IB以便对其进行自定义。我尝试在类ViewControllerB
的IB中创建一个视图控制器,并将其视图之一连接到@IBOutlet var menuView: UIView!
,而不是通过编程方式创建menuView
(如示例中所示)。但是,将nil
作为子视图添加到视图时发现menuView
。任何帮助都会很棒。谢谢!
答案 0 :(得分:0)
一些观察结果:
在该示例中,有一行显示:
let vc = ViewControllerB()
您可以在NIB中定义该视图控制器的视图,这样可以很好地工作。但是,如果您使用情节提要,请将其替换为...
let vc = storyboard!.instantiateViewController(withIdentifier: “identifier")
...其中identifier
是您在IB的“身份检查器”中为该场景提供的一些字符串,作为“故事板ID”。
如果这是由按钮或类似的东西触发的,则您也可以在该示例中删除此gotoVCB
,然后像往常一样在IB中进行模态表示(例如 control -从按钮拖动到下一个场景),然后选择“模态呈现”。但是您必须确保配置了所有init
方法,例如:
class ViewControllerB: UIViewController {
// used if you use NIBs or just call `init()`
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
configure()
}
// used if you use storyboards
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
modalPresentationStyle = .custom
transitioningDelegate = self
}
...
}
与紧迫的问题无关,我建议将that answer’s代码拆分为单独的对象,以防止视图控制器“膨胀”,并更好地将过渡的委托对象,动画控制器等之间的职责分开
例如,也许:
class ViewControllerB: UIViewController {
let customTransitioningDelegate = PopUpMenuTransitioningDelegate()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
func configure() {
modalPresentationStyle = .custom
transitioningDelegate = customTransitioningDelegate
}
}
和
class PopUpMenuTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PopUpMenuAnimationController(transitionType: .presenting)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PopUpMenuAnimationController(transitionType: .dismissing)
}
}
和
class PopUpMenuAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
enum TransitionType {
case presenting
case dismissing
}
let transitionType: TransitionType
init(transitionType: TransitionType) {
self.transitionType = transitionType
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toVC = transitionContext.viewController(forKey: .to),
let fromVC = transitionContext.viewController(forKey: .from) else { return }
switch transitionType {
case .presenting:
containerView.addSubview(toVC.view)
var rect = fromVC.view.bounds
let menuHeight = fromVC.view.bounds.height / 2
rect.origin.y += fromVC.view.bounds.height
rect.size.height = menuHeight
toVC.view.frame = rect
toVC.view.alpha = 0
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
rect.origin.y = menuHeight
toVC.view.frame = rect
toVC.view.alpha = 1
}, completion: { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
case .dismissing:
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
var rect = fromVC.view.frame
rect.origin.y = toVC.view.bounds.height
fromVC.view.frame = rect
fromVC.view.alpha = 0
}, completion: { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
}
这将过渡的委托和动画控制器与视图控制器分离,并允许您在需要时将其与其他视图控制器一起使用。
注意,我对completeTransition
的参数也要多加注意。一旦开始使用交互式过渡,您可能会支持可取消的过渡。