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

SwiftUI如何在导航栏(Navigation Bar)标题下方嵌入分段选择器(Segmented picker)并保留折叠动画

嘿,这个需求我刚好实现过,完全可以做到!下面给你分享一个适配iOS 16+的完整方案,同时也会附上iOS 15的兼容版本,保证分段选择器能完美嵌入导航栏标题下方,还能保留原生的折叠动画效果~

实现方案

核心思路

利用SwiftUI的NavigationStack(iOS 16+)或NavigationView(iOS 15及以下)的工具栏布局能力,将分段选择器放在导航标题的专属下方区域,同时通过原生的滚动折叠配置,让导航栏在滚动时自动收缩,分段选择器也会跟着同步动画,和系统搜索框的表现完全一致。

iOS 16+ 完整代码

这个版本直接利用iOS 16新增的.belowTitle工具栏位置,无需手动调整布局,代码更简洁:

import SwiftUI

struct SegmentedNavView: View {
    // 分段选择器选项
    private let segments = ["全部", "已完成", "待办"]
    @State private var selectedSegment = 0
    
    var body: some View {
        NavigationStack {
            // 模拟长列表用于触发滚动折叠
            ScrollView {
                LazyVStack(spacing: 20) {
                    ForEach(0..<50) { index in
                        Text("列表项 \(index + 1)")
                            .font(.title)
                            .frame(maxWidth: .infinity, alignment: .leading)
                            .padding()
                    }
                }
            }
            .navigationTitle("我的任务")
            .navigationBarTitleDisplayMode(.large)
            // 将分段选择器嵌入导航标题下方
            .toolbar {
                ToolbarItem(placement: .belowTitle) {
                    Picker("", selection: $selectedSegment) {
                        ForEach(0..<segments.count) { index in
                            Text(segments[index])
                                .tag(index)
                        }
                    }
                    .pickerStyle(.segmented)
                    .frame(width: 280) // 自定义宽度让布局更协调
                }
            }
            // 开启导航栏滚动折叠动画
            .toolbarScrollableAxes(.vertical)
            .toolbarBackground(.visible, for: .navigationBar)
            .toolbarBackground(.bar, for: .navigationBar)
        }
    }
}

struct SegmentedNavView_Previews: PreviewProvider {
    static var previews: some View {
        SegmentedNavView()
    }
}

关键细节解释

  • .belowTitle位置:iOS 16专门为导航栏标题下方的内容提供了这个工具栏位置,完美匹配需求,不需要手动堆叠标题和选择器
  • 滚动折叠动画:.toolbarScrollableAxes(.vertical)是开启原生导航栏折叠的关键,滚动列表时,导航栏会自动收缩,分段选择器也会同步缩小并保持在导航栏内
  • 工具栏背景设置:.toolbarBackground(.visible)确保导航栏背景始终可见,避免分段选择器滚动时被隐藏

iOS 15 兼容版本

如果需要支持iOS 15及以下,可以用NavigationView配合.principal工具栏位置实现类似效果:

import SwiftUI

struct SegmentedNavViewiOS15: View {
    private let segments = ["全部", "已完成", "待办"]
    @State private var selectedSegment = 0
    
    var body: some View {
        NavigationView {
            List(0..<50) { index in
                Text("列表项 \(index + 1)")
                    .font(.title)
            }
            .navigationBarTitleDisplayMode(.large)
            .toolbar {
                ToolbarItem(placement: .principal) {
                    // 手动堆叠标题和分段选择器
                    VStack(spacing: 8) {
                        Text("我的任务")
                            .font(.largeTitle)
                            .fontWeight(.bold)
                        Picker("", selection: $selectedSegment) {
                            ForEach(0..<segments.count) { index in
                                Text(segments[index])
                                    .tag(index)
                            }
                        }
                        .pickerStyle(.segmented)
                        .frame(width: 280)
                    }
                }
            }
            .toolbarBackground(.visible, for: .navigationBar)
            .toolbarBackground(.bar, for: .navigationBar)
        }
    }
}

注意事项

  • 可以根据需求调整分段选择器的宽度、颜色等样式,让它和你的App风格统一
  • 如果需要自定义导航栏背景色,只需要修改.toolbarBackground的参数即可,比如.toolbarBackground(Color.blue, for: .navigationBar)
  • 测试时要确保滚动列表足够长,才能触发导航栏的折叠动画

内容的提问来源于stack exchange,提问作者Just A Question

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:08:12