使用NavigationStack和.searchable时如何始终显示大导航标题?
解决方案
当使用.searchable(placement: .navigationBarDrawer(displayMode: .always))时,系统默认会将导航标题切换为紧凑模式,直到滚动页面才会展开大标题——这是抽屉式搜索栏的布局逻辑与大标题初始展示的冲突导致的。以下是两种适用于NavigationStack的可行方案:
方案一:模拟滚动触发大标题初始显示(适配List场景)
通过在页面加载时轻微偏移滚动视图,强制触发大标题展示,同时保留始终显示的抽屉式搜索栏:
struct SearchView: View { @State var searchText = "" @ObservedObject private var viewModel: SearchViewModel var body: some View { NavigationStack(path: $viewModel.path) { List { Text("Simple View") } .navigationBarTitleDisplayMode(.large) .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always)) .onAppear { // 初始轻微偏移滚动视图,触发大标题显示 DispatchQueue.main.async { UIScrollView.appearance().setContentOffset(CGPoint(x: 0, y: -1), animated: false) } } .onDisappear { // 恢复默认偏移,避免影响其他页面 UIScrollView.appearance().setContentOffset(.zero, animated: false) } } } }
方案二:自定义Toolbar布局(完全控制标题与搜索栏)
如果想要彻底摆脱系统布局限制,可以自定义Toolbar,直接放置大标题和搜索栏,确保启动时就展示大标题且搜索栏始终可见:
struct SearchView: View { @State var searchText = "" @ObservedObject private var viewModel: SearchViewModel var body: some View { NavigationStack(path: $viewModel.path) { List { Text("Simple View") } .toolbar { // 自定义大标题 ToolbarItem(placement: .principal) { Text("Search") .font(.system(size: 34, weight: .bold)) } // 始终显示的搜索栏(可调整样式和位置) ToolbarItem(placement: .bottomBar) { TextField("输入搜索内容", text: $searchText) .textFieldStyle(.roundedBorder) .padding(.horizontal) } } .navigationBarTitleDisplayMode(.inline) // 隐藏系统默认标题 } } }
注意事项
- 方案一使用了
UIScrollView.appearance(),必须在onDisappear中恢复默认值,避免影响其他页面的滚动视图。 - 方案二的搜索栏位置可通过
placement参数调整(比如.navigationBarTrailing),样式也可根据需求自定义。
内容的提问来源于stack exchange,提问作者Alessandro Francucci
相关产品推荐
相关产品推荐

