SwiftUI仿Safari导航栏:标题、Done按钮及分段选择器实现问题
复刻Safari书签页面UI的SwiftUI优化方案
需求说明
需要复刻iOS Safari书签页面的核心UI元素:
- 随分段选择器切换的动态标题
- 导航栏右侧的「Done」按钮
- 居中显示的带图标分段选择器(包含书签、阅读列表、历史记录)
- 集成到导航栏下方的筛选搜索框
当前代码存在的问题
- 分段选择器对齐异常,无法匹配Safari的布局
- 搜索框未集成到导航栏区域,和Safari样式不符
- 「Done」按钮与分段选择器出现重叠或错位
修正后的代码
import SwiftUI enum Tab: String, CaseIterable { case bookmarks = "Bookmarks" case readingList = "Reading List" case history = "History" var icon: String { switch self { case .bookmarks: return "book" case .readingList: return "eyeglasses" case .history: return "clock" } } } struct ContentView: View { @State private var selectedTab: Tab = .bookmarks @State private var searchQuery = "" var body: some View { NavigationStack { ScrollView { Text("Content for \(selectedTab.rawValue)") .font(.title) .padding() } .toolbar { // 自定义导航栏顶部:动态标题 ToolbarItem(placement: .navigationBarLeading) { Text(selectedTab.rawValue) .font(.headline) } // 居中的带图标分段选择器 ToolbarItem(placement: .principal) { Picker("", selection: $selectedTab) { ForEach(Tab.allCases, id: \.self) { tab in Image(systemName: tab.icon) .tag(tab) } } .pickerStyle(.segmented) .frame(minWidth: 180) // 固定最小宽度,避免挤压变形 } // 右侧Done按钮 ToolbarItem(placement: .navigationBarTrailing) { Button("Done") { print("Done tapped") } } // 集成式搜索框(嵌入导航栏下方) ToolbarItem(placement: .bottomBar) { TextField("Search", text: $searchQuery) .textFieldStyle(.roundedBorder) .padding(.horizontal) } } .navigationBarTitleDisplayMode(.inline) .toolbarBackground(.visible, for: .navigationBar) } } } #Preview { ContentView() }
问题解决说明
分段选择器对齐问题:
- 取消默认的
navigationTitle绑定,改用.navigationBarLeading位置放置动态标题,避免和.principal区域的分段选择器布局冲突 - 给分段选择器设置固定最小宽度,防止被界面元素挤压变形,匹配Safari的分段器视觉尺寸
- 取消默认的
搜索框集成问题:
- 舍弃默认的
.searchable修饰符,改用.bottomBar位置的ToolbarItem放置自定义搜索框,将其嵌入导航栏下方区域,完全匹配Safari的布局逻辑
- 舍弃默认的
按钮重叠问题:
- 明确分配各Toolbar元素的位置:标题在左侧、分段器居中、Done按钮在右侧,借助SwiftUI的Toolbar自动布局规则避免元素重叠
- 开启
.toolbarBackground(.visible)确保导航栏背景可见,还原Safari的视觉风格
内容的提问来源于stack exchange,提问作者HD Mavani
相关产品推荐
相关产品推荐

