这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
前文
一、目标
实现通讯录的页面。
二、思路
由于篇幅太长,本节只讲述搜索栏。
这个搜索栏其实是一个按钮,通过点击它会打开一个新的搜索页。
所以这个功能,分成2步。
- 第一步,画这个搜索框框,通过点击它打开新页面。
- 第二步,实现这个搜索新页面,增加真的搜索栏。
三、搜索框
首先,搜索框可以分成一个矩形
和HStack(文字加图标)
的结合体,所以使用ZStack结合二者即可。
ScrollView{
ZStack{
Rectangle().fill().frame(height: 50).foregroundColor(.white).cornerRadius(5).padding(12.5)
HStack{
Image(systemName: "magnifyingglass")
Text("搜索")
}.foregroundColor(Color(red: 188/255, green: 188/255, blue: 188/255))
}
}.background(Color(red: 237/255, green: 237/255, blue: 237/255))
- 使用
Rectangle
设置矩形 cornerRadius
设置圆角Color(red: 188/255, green: 188/255, blue: 188/255)
可以设置RGB色彩模式。不过通过取色器获取出来的值要除以255才是真正对应的值。
接下来实现点击打开新页面,但是实际操作微信会发现,打开的动画并非左右滑动打开,而是类似打开全屏的动画模式。
SwiftUI
中提供了这种打开方式,只需要给搜索框增加一个fullScreenCover
属性。
.fullScreenCover(isPresented: $searchFullPagePresented, content: {
Button(action: {
searchFullPagePresented = false
}, label: {
Text("back")
})
}).onTapGesture {
searchFullPagePresented = true
}
- 其中
isPresented
用来控制页面的打开关闭事件。 content
包裹的就是全屏页的内容。onTapGesture
增加触屏点击事件,通过修改searchFullPagePresented=true
来达成打开全屏页的事件。Button
是全屏页中的返回按钮,点击之后返回通讯录。
四、搜索全屏页
这里的难点可以分为2个。
- 1是这个矩形搜索栏的实现
- 2是取消按钮返回通讯录。
返回按钮,上一步中已经实现,通过searchFullPagePresented=false
来实现,所以暂且不谈。
只看第一步,整个搜索栏可以拆分一下。
- 创建一个
SearchFullScreenView.swift
把全屏页的内容抽象出来。 - 整个矩形是一个
ZStack
加Rectangle
即可实现 - 红色的是一个放大镜图标
- 蓝色的是输入框
TextField
- 绿色也是一个语音图标
- 最后通过
HStack
连接起来
所以代码如下
struct SearchFullScreenView: View {
@State var searchText: String = ""
@Binding var searchFullPagePresented: Bool
var body: some View {
ScrollView{
HStack{
ZStack{
Rectangle().fill().frame(height: 50).foregroundColor(.white).cornerRadius(5).padding(12.5)
HStack{
Image(systemName: "magnifyingglass")
TextField("搜索", text: $searchText)
Image(systemName: "mic")
}.padding()
}
Button("取消") {
searchFullPagePresented = false
}.padding(.trailing)
}.background(Color(red: 237/255, green: 237/255, blue: 237/255))
}
}
}
- 这里使用双向绑定
子组件@Binding
加父组件@State
,通过控制searchFullPagePresented
的true
与false
来实现页面的打开与关闭。
五、常用搜索九宫格
SwiftUI
中提供了LazyVGrid
来实现纵向布局的九宫格网格布局。
let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 3)
LazyVGrid(columns: columns) {
ForEach((0..<commonSearchFilter.count), id: \.self) {index in
Text("\(commonSearchFilter[index])").font(.callout).padding(.bottom).foregroundColor(.blue)
}
}.font(.largeTitle)
LazyVGrid
接收一个columns
参数布局设置- 通过
repeating
指定.fixed(100)
固定宽度还是.flexible
弹性宽度 count
指定网格数