在本章中,你将学会构建Search搜索进行列表搜索和TabView底部导航。
在上一章节中,我们完成了一个简单的ColourAtla色卡App,接下来我们继续完善App的相关内容。
首先是SearchBar搜索栏,搜索栏的作用是根据列表的内容进行检索,找出我们需要的色卡。
我们使用TextField输入框来构建SearchBar搜索栏,我们先声明一个变量来存储我们的搜索内容。示例:
@State var search = ""
然后构建SearchBar搜索栏的样式。示例:
// MARK: 搜索
private var SearchBarView: some View {
TextField("搜索颜色值", text: $search)
.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,使用TextField输入框作为搜索栏,然后绑定search内容,然后使用修饰符完善了SearchBar搜索栏的样式。我们先替换原有的CardTitleView看看效果:
为了实现搜索颜色名称的交互,我们需要提供一个方法,搜索列表中的色卡。示例:
// MARK: 搜索颜色方法
func searchColor() {
let query = search.lowercased()
DispatchQueue.global(qos: .background).async {
let filter = cardItems.filter { $0.cardColorRBG.lowercased().contains(query) }
DispatchQueue.main.async {
withAnimation(.spring()) {
self.cardItems = filter
}
}
}
}
上述代码中,我们创建了一个搜索颜色的方法searchColor,通过根据搜索文字内容search,查找cardItems色卡数组中的cardColorRBG卡片颜色值参数,如果匹配成功,就在cardItems色卡数组中找到并展示这个颜色。
我们在SearchBarView视图中,当我们TextField输入框内容变化时调用这个方法。示例:
.onChange(of: search) { _ in
if search != "" {
searchColor()
} else {
search = ""
getColors()
}
}
上述代码中,我们在TextField输入框搜索内容search变量改变时,且search输入内容不为空时调用searchColor搜索颜色的方法,当search输入内容为空时,又重新调用getColors获取颜色的方法,这样,我们就实现了搜索颜色值的交互。
接下来,我们来实现标题栏和搜索栏的切换。
我们尝试在标题栏右侧加入一个搜索图标,点击搜索图标切换到搜索栏,在搜索栏输入框右侧也增加一个取消按钮,点击取消又回到标题栏中。
先声明一个存储变量showSearchBar用于判断切换状态。
@State var showSearchBar = false
然后构建搜索按钮的样式和取消按钮的样式。示例:
// MARK: 搜索icon
private var SearchButtonView: some View {
Button(action: {
withAnimation(.easeOut) {
showSearchBar.toggle()
}
}, label: {
Image(systemName: "magnifyingglass")
.font(.system(size: 20, weight: .bold))
.foregroundColor(.gray)
})
}
// MARK: 取消按钮
private var CloseButtonView: some View {
Button(action: {
withAnimation(.easeOut) {
search = ""
getColors()
showSearchBar.toggle()
}
}, label: {
Text("取消")
.foregroundColor(.gray)
})
}
上述代码中,我们创建了两个视图SearchButtonView和CloseButtonView。
在SearchButtonView视图中,我们使用系统搜索图标做一个搜索按钮操作,点击时更改showSearchBar的状态。
在CloseButtonView视图中,我们使用文字按钮做一个取消按钮的操作,点击时清空输入框的内容search,并且更改showSearchBar的状态,同时调用getColors获取颜色的方法。
完成这些后,我们进行样式的组装,示例:
// MARK: 搜索切换
private var SwitchSearchBar: some View {
HStack(spacing: 20) {
if showSearchBar {
SearchBarView
CloseButtonView
} else {
CardTitleView
Spacer()
SearchButtonView
}
}
.padding(.top, 20)
.padding(.bottom, 10)
.padding(.horizontal)
.zIndex(1)
}
上述代码中,我们构建了一个新的视图SwitchSearchBar。
在SwitchSearchBar视图中,我们根据showSearchBar的状态切换展示搜索栏还是标题栏的内容,并把SwitchSearchBar视图在ContentView主视图中呈现。
我们预览下效果:
我们创建一个新的SwiftUI文件,命名为TabberView。
struct TabberView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
ContentView()
.tabItem {
if self.selectedTab == 0 {
Image(systemName: "house")
} else {
Image(systemName: "house.fill")
}
Text("首页")
}
.tag(0)
Text("我的")
.tabItem {
if self.selectedTab == 1 {
Image(systemName: "person")
} else {
Image(systemName: "person.fill")
}
Text("我的")
}
.tag(1)
}
.accentColor(Color.Hex(0x409EFF))
}
}
上述代码中,我们使用TabView来构建底部导航。
我们声明一个变量selectedTab来跟踪当前选中的是哪一个菜单,然后在TabView中绑定selectedTab的值。我们使用tabItem修饰符来显示当前菜单的内容,并且根据 selectedTab选中的状态修饰底部菜单的图标和文字。
最后我们给选中的菜单加上accentColor选中颜色。
我们预览下效果:
我们把之前章节完成的MineView我的视图也换到TabView底部菜单中,预览看下效果:
之前我们使用ProgressView作为加载中的缺省动画,作为一个ColourAtla色卡App,使用ProgressView作为加载动画,这不够优雅。
我们可以使用SwiftUI官方的rotationEffect修饰符构建一个加载动画,先创建一个新的SwiftUI文件,命名为LoadingView。
首先声明一个变量存储旋转状态,然后构建一个旋转的图片icon。
import SwiftUI
struct LoadingView: View {
@State var show: Bool = false
var body: some View {
Image(systemName: "sun.min.fill")
.resizable()
.foregroundColor(Color.Hex(0xFAD0C4))
.aspectRatio(contentMode: .fit)
.frame(width: 60, height: 60)
.rotationEffect(.degrees(show ? 360 : 0))
}
}
上述代码中,我们使用Image构建了一个加载的图标,然后使用rotationEffect修饰符根据show的状态进行旋转。
为了让加载图标循环旋转,我们创建一个方法doAnimation让show的状态每1秒切换1次。
func doAnimation() {
withAnimation(Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)) {
show.toggle()
}
}
完成后,我们在Image展示时调用doAnimation的方法。
最后,我们在ContentView用LoadingView替换原来的ProgressView,然后查看下效果:
快来动手试试吧!
如果本专栏对你有帮助,不妨点赞、评论、关注~
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。
阅读量:2014
点赞量:0
收藏量:0