SwiftUI中如何设置Toolbar内SearchView的最大宽度?
问题:SwiftUI Toolbar内搜索栏无法设置最大宽度
我是SwiftUI新手,尝试给Toolbar里的搜索栏设置最大宽度,但使用.frame(maxWidth: .infinity)并未生效。
ToolbarView 代码
NavigationView { VStack { contentView } .padding(.top, 10) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { if (hideTitleAndSearchButton) { SearchBarView( searchText: $viewModel.personViewModel.searchText, hideTitleAndSearchButton: Binding(projectedValue: $hideTitleAndSearchButton), viewModel: viewModel.personViewModel ) .frame(maxWidth: .infinity) .animationDisable() } else { Text(title) .font(.system(size: 32)) .bold() } } ToolbarItem(placement: .navigationBarTrailing) { if (!hideTitleAndSearchButton) { if (viewModel.setSearchButtonVisibility) { Image(systemName: "magnifyingglass") .onTapGesture { self.hideTitleAndSearchButton = true } .frame(width: 45, height: 45) .foregroundColor(Color.white) .background(Color.mPurple) .clipShape(Circle()) .animationDisable() } } } } } .frame(maxWidth: .infinity)
SearchBarView 代码
var body: some View { HStack { Image("back_icon") .resizable() .renderingMode(.template) .foregroundColor(.mPurple) .onTapGesture { self.isEditing = false self.searchText = "" self.hideTitleAndSearchButton = false viewModel.isSearchMode = false viewModel.isLoading = true DispatchQueue.main.asyncAfter(deadline: .now() + 1) { viewModel.personPopularList.removeAll() viewModel.getPersonPopular() } } .frame(width: 40, height: 40) .animationDisable() TextField("Search ...", text: $searchText) .padding(7) .padding(.horizontal, 20) .background(Color(.systemGray6)) .cornerRadius(8) .accentColor(.mPurple) .frame(maxWidth: .infinity) .onTapGesture { self.isEditing = true viewModel.isSearchMode = true }.onChange(of: searchText) { searchItem in if (!searchItem.isEmpty) { viewModel.searchText = searchItem.lowercased() let _ = print("searchItem true") } else { viewModel.isSearchMode = false viewModel.personPopularList.removeAll() viewModel.getPersonPopular() let _ = print("searchItem false") } let _ = print("searchItemX: \(searchText)") } .animationDisable() .padding(.trailing, 10) } }
解决方法
ToolbarItem的.navigationBarLeading和.navigationBarTrailing位置有固定宽度限制,直接设置maxWidth: .infinity无法突破这个约束,可通过以下方式解决:
- 更换ToolbarItem的位置:将搜索栏所在的ToolbarItem的
placement从.navigationBarLeading改为.principal,该位置允许视图填充导航栏的全部可用宽度。
修改后的ToolbarItem代码:
ToolbarItem(placement: .principal) { if hideTitleAndSearchButton { SearchBarView( searchText: $viewModel.personViewModel.searchText, hideTitleAndSearchButton: $hideTitleAndSearchButton, viewModel: viewModel.personViewModel ) .frame(maxWidth: .infinity) .animationDisable() } else { Text(title) .font(.system(size: 32)) .bold() } }
- 优化搜索栏内部布局:在SearchBarView的HStack外层添加
.frame(maxWidth: .infinity, alignment: .leading),确保内部元素正确排列且撑满宽度:
var body: some View { HStack { // 原有代码保持不变 } .frame(maxWidth: .infinity, alignment: .leading) }
原理:.principal是导航栏的主内容位置,容器会自动填充导航栏的剩余空间,此时设置maxWidth: .infinity就能让搜索栏撑满宽度。
内容的提问来源于stack exchange,提问作者zack
相关产品推荐
相关产品推荐

