SearchBar搜索栏
首先是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() } }
搜索栏切换
接下来,我们来实现标题栏和搜索栏的切换。
我们尝试在标题栏右侧加入一个搜索图标,点击搜索图标切换到搜索栏,在搜索栏输入框右侧也增加一个取消按钮,点击取消又回到标题栏中。
先声明一个存储变量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
主视图中呈现。
我们预览下效果:
TabView底部导航
我们创建一个新的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
底部菜单中,预览看下效果:
LoadingView加载动画
加载样式
之前我们使用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
,然后查看下效果:
项目预览
快来动手试试吧!