如何让UISheetPresentationController在UITabBar下方展示模态视图?
实现UISheetPresentationController在UITabBar下方的永久模态视图(仿“查找我的”App效果)
要实现sheet视图恰好位于UITabBar下方、tabBar始终可见的效果,可通过自定义detent高度、配置sheet锚点等方式达成,以下是完整实现方案:
完整代码示例
// 创建目标控制器并包装到导航控制器 let targetVC = UIViewController() targetVC.view.backgroundColor = .systemBackground let navVC = UINavigationController(rootViewController: targetVC) // 设置模态展示样式 navVC.modalPresentationStyle = .formSheet // 配置SheetPresentationController if let sheet = navVC.sheetPresentationController, let tabBar = tabBarController?.tabBar { // 计算sheet最大高度:屏幕总高度 - tabBar高度 let maxSheetHeight = UIScreen.main.bounds.height - tabBar.frame.height sheet.detents = [ // 自定义中等高度(可根据需求调整比例) .custom(resolver: { _ in UIScreen.main.bounds.height / 2 }), // 最大高度紧贴tabBar底部 .custom(resolver: { _ in maxSheetHeight }) ] // 显示顶部抓取条 sheet.prefersGrabberVisible = true // 中等高度状态下,tabBar区域保持明亮(不被遮罩变暗) sheet.largestUndimmedDetentIdentifier = .custom(identifier: "mediumDetent") // 禁止滚动到边缘时自动展开sheet sheet.prefersScrollingExpandsWhenScrolledToEdge = false // 设置sheet贴边显示,宽度充满屏幕 sheet.prefersEdgeAttachedInCompactHeight = true sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = false // 将sheet锚定到tabBar,确保位置关联 sheet.sourceView = tabBar sheet.sourceRect = tabBar.bounds } // 从tabBarController的当前选中控制器弹出sheet tabBarController?.selectedViewController?.present(navVC, animated: true)
关键配置说明
- 自定义Detent高度:通过自定义detent计算最大高度,确保sheet顶部不会覆盖tabBar,始终停在tabBar下方。
- 贴边与宽度设置:
prefersEdgeAttachedInCompactHeight = true让sheet贴合屏幕边缘,widthFollowsPreferredContentSizeWhenEdgeAttached = false使sheet宽度充满屏幕,还原系统原生的全屏sheet形态。 - 未变暗区域控制:
largestUndimmedDetentIdentifier指定中等高度状态下,tabBar及底部区域保持明亮,和“查找我的”App交互逻辑一致。 - 锚定TabBar:通过
sourceView和sourceRect将sheet与tabBar绑定,避免屏幕旋转或布局变化时出现位置错位。
注意事项
- 确保在
UITabBarController的上下文环境中present控制器(如从当前选中的子控制器弹出),否则tabBar高度获取可能不准确。 - 若需支持屏幕旋转,可在控制器的
viewWillLayoutSubviews方法中重新计算detent高度,保证sheet始终紧贴tabBar。
内容的提问来源于stack exchange,提问作者Jake Chasan
相关产品推荐
相关产品推荐

