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

在SwiftUI中如何将自定义视图绘制在底部toolbar上方?

问题核心原因

SwiftUI 中 NavigationView(iOS 16+ 推荐替换为 NavigationStack)的底部工具栏属于导航容器的系统级 UI 组件,层级天然高于导航容器内部所有自定义视图,因此在导航容器内部的 ZStack 中添加的所有视图都无法覆盖底部工具栏,这也是你示例代码中 Bottom Text 始终被遮挡的根本原因。


最优解决方案:在导航容器外层添加抽屉层级

将弹出抽屉与导航容器放在同一个外层 ZStack 中,抽屉的层级会高于整个导航容器,自然可以覆盖底部工具栏,完全不需要修改原有页面的工具栏逻辑,也不会触发布局重排。
示例代码如下:

struct ContentView: View {
    // 控制抽屉显隐状态
    @State private var showDrawer = false
    
    var body: some View {
        ZStack(alignment: .bottom) {
            // 原有导航容器逻辑完全不变
            NavigationView {
                VStack {
                    Button("点击弹出抽屉") {
                        withAnimation(.easeInOut) {
                            showDrawer.toggle()
                        }
                    }
                    Spacer()
                    Text("Hello, world!")
                }
                .toolbar {
                    ToolbarItemGroup(placement: .bottomBar) {
                        Text("Bottom Bar")
                    }
                }
            }
            
            // 抽屉视图
            if showDrawer {
                VStack {
                    Text("抽屉内容")
                        .frame(maxWidth: .infinity, maxHeight: 300)
                        .background(.white)
                        .shadow(color: .black.opacity(0.1), radius: 4, y: -2)
                }
                .transition(.move(edge: .bottom))
                // 忽略安全区完全覆盖底部工具栏
                .ignoresSafeArea()
                // 点击抽屉外部收起
                .onTapGesture {
                    withAnimation(.easeInOut) {
                        showDrawer = false
                    }
                }
            }
        }
    }
}

该方案的优势:

  • 无需动态移除/添加工具栏,不存在视图位移的UI异常问题
  • 抽屉的弹出/收起动画流畅,符合系统交互规范
  • 兼容性好,支持iOS 14+所有正式版本,替换为NavigationStack后逻辑完全通用

备选方案:自定义底部工具栏

如果你的底部工具栏定制化需求较高,也可以完全放弃系统bottomBar组件,自己实现底部工具栏,完全控制层级关系:

struct ContentView: View {
    @State private var showDrawer = false
    
    var body: some View {
        NavigationView {
            ZStack(alignment: .bottom) {
                // 页面主内容
                VStack {
                    Button("点击弹出抽屉") {
                        withAnimation(.easeInOut) {
                            showDrawer.toggle()
                        }
                    }
                    Spacer()
                    Text("Hello, world!")
                }
                // 隐藏系统底部工具栏占位
                .toolbar(.hidden, for: .bottomBar)
                
                // 自定义底部工具栏,层级低于抽屉
                HStack {
                    Text("Bottom Bar")
                }
                .frame(maxWidth: .infinity)
                .frame(height: 49) // 与系统底部工具栏默认高度一致
                .background(.bar)
                .shadow(color: .black.opacity(0.1), radius: 0.5, y: -0.5)
                
                // 抽屉视图,层级最高
                if showDrawer {
                    VStack {
                        Text("抽屉内容")
                            .frame(maxWidth: .infinity, maxHeight: 300)
                            .background(.white)
                    }
                    .transition(.move(edge: .bottom))
                    .ignoresSafeArea()
                }
            }
        }
    }
}

该方案的优势:

  • 完全控制工具栏的样式、交互逻辑,灵活性更高
  • 不依赖导航容器的系统组件,后续多端适配成本更低

内容的提问来源于stack exchange,提问作者Yariv Adam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 00:27:04