You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }
}

关键说明

  1. 视图层级控制:ZStack内的顺序决定显示优先级——地图在最底,自定义Sheet在中间,工具栏和搜索栏在最上层,这样Sheet会被工具栏挡住下半部分,实现“在后方”的视觉效果。
  2. 动画模拟:用.offset结合.animation实现类似系统sheet的弹出/收起过渡,通过showSheet状态变量控制位置切换。
  3. 高度适配:通过固定比例设置弹窗高度,和你原本代码中presentationDetents的效果对齐,同时兼容不同iOS版本。

内容的提问来源于stack exchange,提问作者osama abbasi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:05:38