TabView
提供了一个交互式界面,允许用户在其内部的子界面间自由的切换,TabView
有两种显示模式,一个是DefaultTabViewStyle
,另一个是PageTabViewStyle
,本文将对DefaultTabViewStyle
这种类型的基本使用和外观样式设置进行一下探索学习。
基本使用
DefaultTabViewStyle
类型下的TabView
就像我们在UIKit
中用到的UITabViewController
,可以作为构建App的一个基本根视图。
要创建带有Tab选项卡的用户界面,在TabView
中添加视图,并对每个视图添加tabItem(_:)
修饰符即可,比如下面这个简单的示例:
上面代码中,我们在TabView
中添加了3个视图,并且给每个视图都添加了tabItem(_:)
修饰符,该修饰符的闭包内支持传入一个Label
组件或者Text
组件加Image
的组合方式。
不管是哪种方式都不支持外观的设置。如果用Text
和Image
组合的方式,添加了除了这两个组件以外的组件,那也是没用的,系统只会认添加的第一个Text
和第一个Image
,其他的都忽略了。
另外可以添加.badge()
修饰符,传入一个字符串,如下:
默认badge
是红色背景白色文字。
在创建TabView
的时候还支持传入一个selection
值,用来记录当前选中的tab,当切换tab的时候,selection
读取每个子界面的tag
值。下面将代码加入tag
,并将代码进行一下优化,首先定义一个TabType
枚举,定义好要显示的界面,包括界面的文字和图标。
enum TabType: Int, Hashable {
case home
case videos
case message
var title: String {
switch self {
case .home:
return "Home"
case .videos:
return "Videos"
case .message:
return "Message"
}
}
var image: String {
switch self {
case .home:
return "house.fill"
case .videos:
return "video.fill"
case .message:
return "message.fill"
}
}
}
有了这个后body
的代码优化为:
@State private var selectedTab: TabType = .home
var body: some View {
TabView(selection: $selectedTab) {
HomeView(selectedTab: $selectedTab)
.tabItem {
Text(TabType.home.title)
Image(systemName: TabType.home.image)
}
.tag(TabType.home)
VideosView()
.tabItem {
Label(TabType.home.title, systemImage: TabType.home.image)
}
.tag(TabType.videos)
MessageView()
.tabItem {
Text(TabType.home.title)
Image(systemName: TabType.home.image)
}
.badge("8")
.tag(TabType.message)
}
}
上面定义了TabType
类型的selectedTab
属性,默认值是.home
,即默认显示Home
界面。我们将selectedTab
绑定到TabView
中,并对每个子界面添加.tag()
修饰符,传入对应的tag
,这里的tag
采用枚举自身的值。
界面切换只要改变selectedTab
的值即可,在Home
界面添加了一个Button,点击后跳转到Message
界面,Home
界面作为一个单独的界面,定义如下:
struct HomeView: View {
@Binding var selectedTab: TabType
var body: some View {
ZStack {
Color.cyan
.ignoresSafeArea(edges: .top)
Button(action: {
selectedTab = TabType.message
}, label: {
Text("Go to Message page")
.padding()
.background(Color.red)
.foregroundColor(.white)
.clipShape(Capsule())
})
}
}
}
Home
界面定义了一个@Bingding
修饰的selectedTab
变量,用来绑定父界面的selectedTab
变量,这样在Home
界面改动selectedTab
变量,父界面的selectedTab
也会改变。
效果图如下:
样式设置
与之前的UIKit
TabBar
类似,选中的Tab默认为蓝色,而未选中的为灰色。另外,在UIKit
中,整个标签栏默认有一个背景。
然而,如果想改变颜色来匹配我们自己App的主题,例如,选中是Tab的文字和图片是其他颜色,以及badge
的背景色和颜色等等。
下面我们将使用的UIKit
外观API
,来设置TabView
的外观样式,让我们看看下面的代码。
先说一下,给TabView
组件添加.tint()
修饰符,可以改变TabItem
选中时的颜色,其他的就得靠UIKit
的API
了。
设置选中的TabItem的颜色
.tint(Color.red) // 设置选中的tabitem的颜色。
设置未选中的TabItem的颜色
UITabBar.appearance().unselectedItemTintColor = .systemBrown
设置badge的背景色
UITabBarItem.appearance().badgeColor = .green
设置badge中文字的样式
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.red, .font: UIFont.boldSystemFont(ofSize: 14)], for: .normal) // 未选中时
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.blue], for: .selected) // 选中时
设置TabBar的背景色
UITabBar.appearance().backgroundColor = .yellow
设置TabItem中文字和图片的间距和偏移量
UITabBarItem.appearance().titlePositionAdjustment = UIOffset(horizontal: 0, vertical: 5)
上面的这些设置,我们可以在初始化组件的时候设置,也可以在.onAppear
中设置。
.onAppear {
UITabBar.appearance().unselectedItemTintColor = .systemBrown
UITabBarItem.appearance().badgeColor = .green
UITabBar.appearance().backgroundColor = .yellow
UITabBarItem.appearance().titlePositionAdjustment = UIOffset(horizontal: 0, vertical: 5)
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.red, .font: UIFont.boldSystemFont(ofSize: 14)], for: .normal)
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.blue], for: .selected)
}
写在最后
以上就是TabView
的基本用法及样式设置,希望对大家能有所帮助,下一篇文章继续看一下PageTabViewStyle
样式下的TabView
。
最后,希望能够帮助到有需要的朋友,如果您觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。
完整Demo代码如下:
import SwiftUI
enum TabType: Int, Hashable {
case home
case videos
case message
var title: String {
switch self {
case .home:
return "Home"
case .videos:
return "Videos"
case .message:
return "Message"
}
}
var image: String {
switch self {
case .home:
return "house.fill"
case .videos:
return "video.fill"
case .message:
return "message.fill"
}
}
}
struct TabViewDemo: View {
@State private var selectedTab: TabType = .home
var body: some View {
TabView(selection: $selectedTab) {
HomeView(selectedTab: $selectedTab)
.tabItem {
Text(TabType.home.title)
Image(systemName: TabType.home.image)
}
.tag(TabType.home)
VideosView()
.tabItem {
Label(TabType.home.title, systemImage: TabType.home.image)
}
.tag(TabType.videos)
MessageView()
.tabItem {
Text(TabType.home.title)
Image(systemName: TabType.home.image)
}
.badge("8")
.tag(TabType.message)
}
.tint(Color.red)
.onAppear {
UITabBar.appearance().unselectedItemTintColor = .systemBrown
UITabBarItem.appearance().badgeColor = .green
UITabBar.appearance().backgroundColor = .yellow
UITabBarItem.appearance().titlePositionAdjustment = UIOffset(horizontal: 0, vertical: 5)
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.red, .font: UIFont.boldSystemFont(ofSize: 14)], for: .normal)
UITabBarItem.appearance().setBadgeTextAttributes([.foregroundColor: UIColor.blue], for: .selected)
}
}
}
#Preview {
TabViewDemo()
}
struct HomeView: View {
@Binding var selectedTab: TabType
var body: some View {
ZStack {
Color.cyan
.ignoresSafeArea(edges: .top)
Button(action: {
selectedTab = TabType.message
}, label: {
Text("Go to Message page")
.padding()
.background(Color.red)
.foregroundColor(.white)
.clipShape(Capsule())
})
}
}
}
struct VideosView: View {
var body: some View {
ZStack {
Color.blue
.ignoresSafeArea(edges: .top)
}
}
}
struct MessageView: View {
var body: some View {
ZStack {
Color.red
.ignoresSafeArea(edges: .top)
}
}
}