目前在半angular父控制器中的模态视图控制器

我正试图在其他视图控制器大小为一半父视图控制器呈现模式视图控制器。 但它始终以全屏显示。

我已经创build了自由大小的视图控制器在我的故事板固定帧大小。 320×250。

var storyboard = UIStoryboard(name: "Main", bundle: nil) var pvc = storyboard.instantiateViewControllerWithIdentifier("CustomTableViewController") as ProductsTableViewController self.presentViewController(pvc, animated: true, completion: nil) 

我试图设置frame.superview并没有帮助。

图片的例子

请指教。

你可以使用UIPresentationController来实现这一点。

为此,您让呈现ViewController实现UIViewControllerTransitioningDelegate并返回您的PresentationController的一半大小的演示文稿:

 func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? { return HalfSizePresentationController(presentedViewController: presented, presentingViewController: presenting) } 

在呈现时,您将演示文稿样式设置为.Custom并设置您的转换委托:

 pvc.modalPresentationStyle = UIModalPresentationStyle.Custom pvc.transitioningDelegate = self 

演示文稿控制器只返回您的演示视图控制器的框架:

 class HalfSizePresentationController : UIPresentationController { override func frameOfPresentedViewInContainerView() -> CGRect { return CGRect(x: 0, y: 0, width: containerView.bounds.width, height: containerView.bounds.height/2) } } 

这是完整的工作代码:

 class ViewController: UIViewController, UIViewControllerTransitioningDelegate { @IBAction func tap(sender: AnyObject) { var storyboard = UIStoryboard(name: "Main", bundle: nil) var pvc = storyboard.instantiateViewControllerWithIdentifier("CustomTableViewController") as UITableViewController pvc.modalPresentationStyle = UIModalPresentationStyle.Custom pvc.transitioningDelegate = self pvc.view.backgroundColor = UIColor.redColor() self.presentViewController(pvc, animated: true, completion: nil) } func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? { return HalfSizePresentationController(presentedViewController: presented, presentingViewController: presentingViewController) } } class HalfSizePresentationController : UIPresentationController { override func frameOfPresentedViewInContainerView() -> CGRect { return CGRect(x: 0, y: 0, width: containerView.bounds.width, height: containerView.bounds.height/2) } } 

这将是一个干净的架构师,如果你推你的ViewController的UIViewControllerTransitioningDelegate一些委托方法,希望是一半模式。

假设我们有ViewControllerA呈现一半模式的ViewControllerB

ViewControllerA只是用自定义的modalPresentationStyle呈现ViewControllerB

 func gotoVCB(_ sender: UIButton) { let vc = ViewControllerB() vc.modalPresentationStyle = .custom present(vc, animated: true, completion: nil) } 

在ViewControllerB中:

 import UIKit final class ViewControllerB: UIViewController { lazy var backdropView: UIView = { let bdView = UIView(frame: self.view.bounds) bdView.backgroundColor = UIColor.black.withAlphaComponent(0.5) return bdView }() let menuView = UIView() let menuHeight = UIScreen.main.bounds.height / 2 var isPresenting = false init() { super.init(nibName: nil, bundle: nil) modalPresentationStyle = .custom transitioningDelegate = self } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .clear view.addSubview(backdropView) view.addSubview(menuView) menuView.backgroundColor = .red menuView.translatesAutoresizingMaskIntoConstraints = false menuView.heightAnchor.constraint(equalToConstant: menuHeight).isActive = true menuView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true menuView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true menuView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewControllerB.handleTap(_:))) backdropView.addGestureRecognizer(tapGesture) } func handleTap(_ sender: UITapGestureRecognizer) { dismiss(animated: true, completion: nil) } } extension ViewControllerB: UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self } func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 1 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let containerView = transitionContext.containerView let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) guard let toVC = toViewController else { return } isPresenting = !isPresenting if isPresenting == true { containerView.addSubview(toVC.view) menuView.frame.origin.y += menuHeight backdropView.alpha = 0 UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: { self.menuView.frame.origin.y -= self.menuHeight self.backdropView.alpha = 1 }, completion: { (finished) in transitionContext.completeTransition(true) }) } else { UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: { self.menuView.frame.origin.y += self.menuHeight self.backdropView.alpha = 0 }, completion: { (finished) in transitionContext.completeTransition(true) }) } } } 

结果:

在这里输入图像说明

所有代码都发布在我的Github上

Jannis很好地抓住了整体战略。 它在iOS 9.x中并不适用于swift 3.在提交VC时,启动VC所采取的行动与上面介绍的相似,只是做了一些小的改动,如下所示:

 let storyboard = UIStoryboard(name: "Main", bundle: nil) let pvc = storyboard.instantiateViewController(withIdentifier: "SomeScreen") as SomeViewController pvc.modalPresentationStyle = .custom pvc.transitioningDelegate = self present(pvc, animated: true, completion: nil) 

要在相同的呈现VC上实现UIViewControllerTransitioningDelegate ,语法与在https://stackoverflow.com/a/39513247/2886158中的SO答案中突出显示的内容相当不同。 这是我最棘手的部分。 这里是协议实现:

 func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return HalfSizePresentationController(presentedViewController:presented, presenting: presenting) } 

对于UIPresentationController类,我必须覆盖variablesframeOfPresentedViewInContainerView ,而不是方法,如下所示:

 class HalfSizePresentationController: UIPresentationController { override var frameOfPresentedViewInContainerView: CGRect { return CGRect(x: 0, y: 0, width: containerView!.bounds.width, height: containerView!.bounds.height/2) } } 

演讲结束后,如何解除观点有一些问题。 你可以像所有其他的VC一样,在你提交的VC上实现所有通常的逻辑。 我实现了一个动作来解散SomeViewController的视图,当用户在提交的VC之外进行SomeViewController时。

为了增加Jannis的答案:

如果你的popup窗口是一个UIViewController,你可以在load / setup上添加一个表格,你需要确保你创build的表格框架与实际视图的宽度相匹配。

例如:

 let tableFrame: CGRect = CGRectMake(0, 0, chosenWidth, CGFloat(numOfRows) * rowHeight) 

其中chosenWidth是您在自定义类中设置的宽度(在上面: containerView.bounds.width

你不需要强制Cell本身的任何东西,因为表格容器(至less在理论上)应该强制单元格的宽度。

我使用下面的逻辑来呈现一半的ViewController

  let storyboard = UIStoryboard(name: "Main", bundle: nil) let expVC = storyboard.instantiateViewController(withIdentifier: "AddExperinceVC") as! AddExperinceVC expVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext self.present(expVC, animated: true, completion: nil)