SwiftUI组件之TabView

2,624 阅读2分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

一、底部导航

通常SwiftUI组件TabView是作为底部导航栏使用的。

屏幕录制2021-08-08 11.54.58.gif

struct ContentView: View {
    var body: some View {
        TabView{
            Text("第一栏页面").foregroundColor(.blue).tabItem {
                Image(systemName: "1.square")
                Text("第一栏")
            }
            Text("第二栏页面").foregroundColor(.green).tabItem {
                Image(systemName: "2.square")
                Text("第二栏")
            }
            Text("第三栏页面").foregroundColor(.red).tabItem {
                Image(systemName: "3.square")
                Text("第三栏")
            }
        }
    }
}

image.png

  • tabItem修饰的红色部分,是导航栏导向的View或者说页面。
  • tabItem包裹的绿色部分,就是导航栏按钮本身。默认是纵向排列。

二、定向跳转

点击第一栏就会跳转到第一栏导向的页面,OK,这没问题。

如果有个需求,希望不用点击导航按钮也能跳转到该导向的页面,该怎么办呢。举例来说,第一栏页面,增加一个按钮,通过点击这个按钮,能够跳转到第三栏导向的页面。

graph LR
第三栏导航按钮 --> 第三栏页面

非导航按钮 --> 第三栏页面

总结起来需要三步:

第一步,将每个导航栏打上标记(tag)

TabView{
    Text("第一栏页面").foregroundColor(.blue).tabItem {
        Image(systemName: "1.square")
        Text("第一栏")
    }.tag(1)
    Text("第二栏页面").foregroundColor(.green).tabItem {
        Image(systemName: "2.square")
        Text("第二栏")
    }.tag(2)
    Text("第三栏页面").foregroundColor(.red).tabItem {
        Image(systemName: "3.square")
        Text("第三栏")
    }.tag(3)
}

第二步,TabView有个参数selection,是Binding类型。所以通过改变该变量的值,TabView就会指向对应的tab栏。

根据tag值匹配,selection=1就会跳转到tag1的页面。默认不指定,tag0开始计数。此例手动增加tag是为了更清晰的了解其中的作用。

struct ContentView: View {
    
    @State var tabViewSelected: Int = 1
    
    var body: some View {
       
        TabView(selection: $tabViewSelected){
            Text("第一栏页面").foregroundColor(.blue).tabItem {
                Image(systemName: "1.square")
                Text("第一栏")
            }.tag(1)
            Text("第二栏页面").foregroundColor(.green).tabItem {
                Image(systemName: "2.square")
                Text("第二栏")
            }.tag(2)
            Text("第三栏页面").foregroundColor(.red).tabItem {
                Image(systemName: "3.square")
                Text("第三栏")
            }.tag(3)
        }
    }
}

  • 定义变量tabViewSelected,通过@State使其为引用变量。
  • tabViewSelected作为参数传入TabViewselection中,并在变量前增加$符号,将其转换为Binding

第三步,也即最后一步。增加一个按钮,改变tabViewSelected值。

VStack{
    Text("第一栏页面")
    Button(action: {
        tabViewSelected = 3
    }, label: {
        Text("跳转到第三栏")
    }).padding()
}.foregroundColor(.blue).tabItem {
    Image(systemName: "1.square")
    Text("第一栏")
}.tag(1)

最终效果如下

屏幕录制2021-08-08 14.42.26.gif

三、轮播图

TabView除此之外还有一个作用,就是实现轮播图。

屏幕录制2021-08-08 14.46.36.gif

代码如下:

TabView{
    Rectangle().foregroundColor(.blue).tag(1)
    Rectangle().foregroundColor(.orange).tag(2)
    Rectangle().foregroundColor(.red).tag(3)
}.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))

与导航栏相比唯一的区别就是:

  • 不需要.tabItem属性
  • 需要指定.tabViewStyle(PageTabViewStyle())

tabViewStyle只有两种样式,默认不指定或者指定为.tabViewStyle(DefaultTabViewStyle())都是导航栏;只有指定.tabViewStyle(PageTabViewStyle())的情况下才是轮播图。

PageTabViewStyle可以指定索引展示模式即indexDisplayMode

  • automatic,默认不传值或者传automatic都是自动模式,即轮播的元素只有1个的时候,不显示底部的导航圈圈;反之,有1个以上元素的时候,则会显示导航圈圈。
  • .never则是完全禁用了导航圈圈了。
  • .always则是始终显示。

同上例中的导航栏一样,轮播图同样可以使用selection来指定展示的元素。