SwiftUI实现Bottom Sheet显示在Bottom Toolbar后方的方案咨询
实现SwiftUI Bottom Sheet显示在底部工具栏后方的解决方案
要让Bottom Sheet显示在底部工具栏后方,系统自带的.sheet修饰符没法做到——它的层级默认在整个NavigationView之上,包括底部工具栏。你得通过自定义弹窗+调整视图层级的方式来实现,以下是具体方案:
核心思路
把底部工具栏放在ZStack的最上层,自定义的Bottom Sheet放在工具栏下方(ZStack的中间层),通过状态变量控制弹窗的显示/隐藏,配合动画模拟系统sheet的弹出效果。
修改后的代码
struct Track1: View { @State private var showSheet = false @State private var searchText = "" // 适配不同iOS版本的弹窗高度 private let sheetMediumHeight: CGFloat = UIScreen.main.bounds.height * 0.5 private let sheetSmallHeight: CGFloat = UIScreen.main.bounds.height * 0.1 var body: some View { NavigationView{ ZStack { // 底层:地图视图 MapView(mapType: .standard, showsUserLocation: true) // 中间层:自定义Bottom Sheet(在工具栏下方) VStack { Spacer() ZStack { if #available(iOS 16, *) { VStack{ Text("SHEET IS OPEN") } .frame(height: showSheet ? sheetMediumHeight : sheetSmallHeight) } else { VStack{ Text("SHEET IS OPEN") } .frame(height: showSheet ? sheetMediumHeight : sheetSmallHeight) } } .background(Color.white) .cornerRadius(20) .offset(y: showSheet ? 0 : UIScreen.main.bounds.height) .animation(.easeInOut, value: showSheet) } // 上层:搜索栏 VStack(spacing:20){ VStack{ HStack{ Image(systemName: "magnifyingglass") TextField("Search..",text: $searchText) } .padding() .background(Color.white) .cornerRadius(20) .padding(.top,30) .padding(.horizontal,30) } Spacer() } } .toolbar { // 最上层:底部工具栏 ToolbarItem(placement:.bottomBar) { HStack(spacing:11){ Button{ showSheet.toggle() } label: { VStack { Image(icon: .home_g) .renderingMode(.template) .resizable() .frame(width: 30, height: 30) Text("Home") } .frame(width: 65, height: 65) .cornerRadius(25) } } } } .accentColor(Color(hex: 0xFA6109)) } } } // 自定义组件占位(根据你的实际实现替换) enum Icon { case home_g } extension Image { init(icon: Icon) { self.init(systemName: "house") } } struct MapView: View { var mapType: Any var showsUserLocation: Bool var body: some View { Color.blue } }
关键说明
- 视图层级控制:ZStack内的顺序决定显示优先级——地图在最底,自定义Sheet在中间,工具栏和搜索栏在最上层,这样Sheet会被工具栏挡住下半部分,实现“在后方”的视觉效果。
- 动画模拟:用
.offset结合.animation实现类似系统sheet的弹出/收起过渡,通过showSheet状态变量控制位置切换。 - 高度适配:通过固定比例设置弹窗高度,和你原本代码中
presentationDetents的效果对齐,同时兼容不同iOS版本。
内容的提问来源于stack exchange,提问作者osama abbasi
相关产品推荐
相关产品推荐

