UIViewController 的动态高度显示为模式弹出窗口

Posted

技术标签:

【中文标题】UIViewController 的动态高度显示为模式弹出窗口【英文标题】:Dynamic height for UIViewController shown as modal popup 【发布时间】:2019-01-05 19:23:00 【问题描述】:

我目前正在尝试实现一个自定义UIViewController,其中包含一个UINavigationController。这是一个模态视图,将在屏幕底部可见,用户可以在此模态视图内导航有不同的选项。 UIViewController 的背景设置为清除,因此它显示为已经可见屏幕的覆盖。

我现在已经设法像这样设置和展示我的UIViewController

    let modalController = ModalController()
    modalController.modalPresentationStyle = .overCurrentContext
    self.present(modalController, animated: true, completion: nil)

在这个UIViewController里面我是这样做的:

var popupController: UINavigationController = 
    let popupController = UINavigationController(rootViewController: ModalStart())
    return popupController
()

var modalPopup: UIView = 
    let modalPopup = UIView()
    modalPopup.translatesAutoresizingMaskIntoConstraints = false
    modalPopup.backgroundColor = .white
    modalPopup.isUserInteractionEnabled = true
    return modalPopup
()

view.addSubview(modalPopup)
modalPopup.addSubview(popupController.view)

modalPopup.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
modalPopup.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
modalPopup.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
modalPopup.heightAnchor.constraint(equalToConstant: 500).isActive = true

这很好用,但您可能已经猜到了,高度设置为 500 的固定常数。这适用于我的 iPhone X,但在 iPhone 5s 上会有所不同。当我浏览UINavigationController 时,它也不允许我相应地更改高度,因为不同viewControllers 的高度会有所不同。

有谁知道我如何做到这一点?我已经在我的rootViewController (ModalStart) 中添加了一个自定义 ContainerView,但我无法直接访问 popupController.containerView.frame.height(因为 popupController 是一个UINavigationController)。我还尝试将 heightAnchor 设为变量并将其设置在 ModalStart() 的 viewDidLayoutSubviews() 中,但这也不起作用,并且会以不同的高度不断触发(如果我打印高度,它有时会返回 480,有时会返回 0,非常那里有奇怪的行为)。

我想知道对于我的具体情况最好的方法是什么。非常感谢任何指出我正确方向的东西!

【问题讨论】:

modalpopup.topanchor 工作了吗? 你是什么意思?我可以设置modalPopup.topAnchor,是的。如果我将它限制在视图的 topAnchor 上,并设置一个常数,比如说 300,它显示得非常好。但这不是动态的。我试图在 viewDidLayoutSubviews() 之后计算 containerView 的高度,并用整个屏幕的高度减去然后计算的 containerView 的高度来相应地更改它。这最初是可行的,但后来我无法更改高度,因为 popupController 的高度(内部有 UINavigationController)保持与初始高度相同。 为什么不将 heightAnchor 设置为取决于 screenSize 的常量。例如modalPopup.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height/yourConstant).isActive = true 这样你就可以让它根据屏幕大小动态工作。如果您不想使用 UIScreen 大小,也可以使用 ViewController 边界 那不允许我根据子视图设置高度。有一些子视图可以有不同的高度,例如多行 UILabel。当 UINavigationController 被推送到另一个具有另一个高度的视图时,也很难相应地更改高度。 你能张贴你想要得到的截图吗?我有点难以理解。 【参考方案1】:

我将向您展示一个简单的方法。据我所见,最好的方法是使用 modalView 的 dataSource 模型并从那里计算高度。例如,如果您有一个图像和一个标签,哪些高度是已知的,如果不能计算,您可以将其作为 modalView 的数据源发送。现在,如果下一个 modalView 将只有 6 个标签,那么再次计算出适合所有标签所需的高度将很容易。通过使用 dataSource 模型,您可以在过渡到下一个 modalView 之前预先计算所有高度。我在这里为您整理了一个简单的示例:https://github.com/galots/VariableModal

如果您单击显示为 Present 的按钮,则会显示新的 viewController,并且 modalView 将显示初始约束。然后,如果您单击下一步,模态视图高度将根据数据源进行相应更新。在这种情况下,dataSource 只是一个CGFloat 的数组,只是为了便于理解。此外,请注意 modalView 是 UIView 的子类,因此您可以根据需要更新其高度约束。

希望对你有帮助。

【讨论】:

感谢您的努力!然而,我似乎无法找到相关代码,当我在 Xcode 中运行时,我什么也看不到,只有一个白色窗口。能否链接到相关代码或文件? 对不起。发布时出错。给你:github.com/galots/VariableModal 哇,太棒了!非常感谢您的榜样!

以上是关于UIViewController 的动态高度显示为模式弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章

swift 动态设置UILabel的高度

UIViewController 中的帧大小问题

在 UITableView 上实现动态高度

UIScrollView 未显示在 UIViewController 上

具有动态高度单元格但所有单元格同时显示的 iOS 表格视图

自动调整大小(动态高度)表格视图单元格的问题