在本章中,你将学会如何使用TextField
输入框构建一个SearchBar搜索栏。
在很多App中,我们都可以看到SearchBar
搜索栏的身影,比如用来搜索某条资讯,搜索某个联系人,亦或者搜索某个功能……
那么这一章节,我们就来学习下如何创建一个简答的SearchBar
搜索栏。
那么,我们开始吧。
首先,创建一个新项目,命名为SwiftUISearchBar
。
UI部分
我们看到SearchBar
搜索栏的样式其实就是一个TextField
输入框,我们在里面输入文字作为搜索条件,TextField
输入框输入的内容再关联SearchBar
组件,达到搜索的目的。
我们构建一个简单的SearchBarView
搜索栏视图。
// SearchBarView搜索栏视图 struct SearchBarView: View { @Binding var text: String @State private var offset: CGFloat = .zero // 使用.animation防止报错,iOS15的特性 var body: some View { TextField("搜你想看的", text: $text) .padding(7) .padding(.horizontal, 25) .background(Color(.systemGray6)) .cornerRadius(8) .overlay( Image(systemName: "magnifyingglass") .foregroundColor(.gray) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).padding(.leading, 8) ) .padding(.horizontal, 10) } }
逻辑部分
然后,我们思考下SearchBarView
搜索栏的逻辑。
当我们SearchBarView
搜索栏没有输入内容时,显示的是“搜你想看的
”文字,那么当我们在TextField
输入内容的时候, 应该要删除placehoder
文字。
我们可以定义一个TextField
输入框是否正在编辑isEditing
的状态,通过isEditing
是否处于编辑状态来判断。
@State private var isEditing = false
当我们点击TextField
输入框输入的时候,isEditing
状态为true
,同时
TextField
输入框内部右侧会显示一个清除图标,点击清除图标可以清空我们输入的内容。
而且清除图标和TextField
输入框是HStack
横向排布,我们完成下交互逻辑。
//点击时 .onTapGesture { self.isEditing = true }
//编辑时显示清除按钮 if isEditing { Button(action: { self.text = "" }) { Image(systemName: "multiply.circle.fill") .foregroundColor(.gray) .padding(.trailing, 8) } }
另外,当我们isEditing
是否处于编辑状态时,SearchBarView
搜索栏应该右边空出一个位置,显示搜索文字按钮,点击搜索时,isEditing
恢复到初始false
状态。
搜索按钮和整个TextField
输入框也是HStack
横向排布。
// 搜索按钮 if isEditing { Button(action: { self.isEditing = false self.text = "" }) { Text("搜索") } .padding(.trailing, 10) .transition(.move(edge: .trailing)) .animation(.default, value: offset) }
我们在模拟器中预览效果。
但这里我们发现一个问题,当我们点击“搜索
”按钮的时候,虽然SearchBarView
搜索栏恢复初始状态了,但是keyboard
键盘没有自动收下去。
我们需要额外添加一个收起keyboard
键盘的方法,代码如下:
// 收起键盘 UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil,
这样,我们就实现了点击“搜索
”时,清空TextField
输入框文字,恢复到初始状态
,并且收起keyboard
键盘。
完整代码如下:
import SwiftUI struct ContentView: View { @State var text: String = "" var body: some View { VStack { SearchBarView(text: $text) .padding() Spacer() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } // SearchBarView搜索栏视图 struct SearchBarView: View { @Binding var text: String @State private var isEditing = false @State private var offset: CGFloat = .zero //使用.animation防止报错,iOS15的特性 var body: some View { HStack { TextField("搜你想看的", text: $text) .padding(7) .padding(.horizontal, 25) .background(Color(.systemGray6)) .cornerRadius(8) .overlay( HStack { Image(systemName: "magnifyingglass") .foregroundColor(.gray) .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) .padding(.leading, 8) // 编辑时显示清除按钮 if isEditing { Button(action: { self.text = "" }) { Image(systemName: "multiply.circle.fill") .foregroundColor(.gray) .padding(.trailing, 8) } } } ) .padding(.horizontal, 10) // 点击时 .onTapGesture { self.isEditing = true } // 搜索按钮 if isEditing { Button(action: { self.isEditing = false self.text = "" // 收起键盘 UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) }) { Text("搜索") } .padding(.trailing, 10) .transition(.move(edge: .trailing)) .animation(.default, value: offset) } } } }
快来动手试试吧!