TabView in SwiftUI

493 阅读2分钟

TabView 作为一个很强大的组件,几乎很多app都会用到。它方便的管理不同业务模块的UI显示。

struct TabViewSample: View {
    var body: some View {
        TabView {
            Text("首页")
                .font(.title)
                .fontWeight(.semibold)
                .tabItem {
                    Image(systemName: "house")
                    Text("首页")
                }
            
            Text("📚大全")
                .tabItem {
                    Image(systemName: "book.closed")
                    Text("书籍")
                }
            
            Text("设置")
                .tabItem {
                    Image(systemName: "gear")
                    Text("设置")
                }
        }
        .tint(Color.purple)
    }
}

image.png

以上就是最简单的示例,我们可以轻松的改变它的外观颜色,使用tint即可。默认是蓝色,我们的例子中使用的紫色。

Tab 切换

我们实现一个在首页里面点击按钮跳转到setting页面的需求。我把代码稍微进行了改造,给首页加入了一个button

struct TabViewSample: View {
    
    @State var selectedTab: Int = 0
    
    var body: some View {
        TabView(selection: $selectedTab) {
            VStack {
                Text("首页")
                    .font(.title)
                    .fontWeight(.semibold)
                Button(action: {
                    
                }, label: {
                    Text("切换到setting tab")
                        .foregroundColor(.white)
                        .font(.headline)
                        .padding()
                        .background(Color.purple.cornerRadius(10))
                })
            }
            .tabItem {
                Image(systemName: "house")
                Text("首页")
            }
            .tag(0)
            
            Text("📚大全")
                .tabItem {
                    Image(systemName: "book.closed")
                    Text("书籍")
                }
                .tag(1)
            
            Text("设置")
                .tabItem {
                    Image(systemName: "gear")
                    Text("设置")
                }
                .tag(2)
        }
        .tint(Color.purple)
    }
}

但是问题来了,这样会显得我们的代码非常长。是时候进行提取一下代码做简化了。

我们会将首页的VStack里面的内容提取为一个组件。一下是组件的代码。

struct MainView: View {
    var body: some View {
        VStack {
            Text("首页")
                .font(.title)
                .fontWeight(.semibold)
            Button(action: {
                
            }, label: {
                Text("切换到setting tab")
                    .foregroundColor(.white)
                    .font(.headline)
                    .padding()
                    .background(Color.purple.cornerRadius(10))
            })
        }
    }
}

调用变成:

MainView()
                .tabItem {
                    Image(systemName: "house")
                    Text("首页")
                }
                .tag(0)

这样有利于代码的整洁,其他人看了也不会因为代码过长而感到头疼。

那么改如何实现点击首页的Button切换到Setting页面呢?

由于我们操作的对象不在一个视图层级内,我们需要在MainView点击,然后来改变父类TabView的切换。所以我们需要使用到之前说过的一个属性包装起@binding来实现

我们把Setting Tab的内容也稍微改变了一下,便于识别

ZStack {
                Color.blue
                    .edgesIgnoringSafeArea(.top)
                
                VStack {
                    Text("设置")
                        .font(.title)
                        .fontWeight(.semibold)
                }
            }
            .tabItem {
                Image(systemName: "gear")
                Text("设置")
            }
            .tag(2)

我们现在就可以实现上述效果了,具体效果如下:

111.gif

Badge

tab上面的小红点很简单,只需要在对应想实现的地方加入一下方法即可

MainView(selectedTab: $selectedTab)
                .badge(2)
                .tabItem {
                    Image(systemName: "house")
                    Text("首页")
                }
                .tag(0)

image.png

首页的Tab上面就有对应的Badge显示了

最后整体代码是这样的


struct TabViewSample: View {
    
    @State var selectedTab: Int = 0
    
    var body: some View {
        TabView(selection: $selectedTab) {
            MainView(selectedTab: $selectedTab)
                .badge(2)
                .tabItem {
                    Image(systemName: "house")
                    Text("首页")
                }
                .tag(0)
            
            Text("📚大全")
                .tabItem {
                    Image(systemName: "book.closed")
                    Text("书籍")
                }
                .tag(1)
            
            ZStack {
                Color.blue
                    .edgesIgnoringSafeArea(.top)
                
                VStack {
                    Text("设置")
                        .font(.title)
                        .fontWeight(.semibold)
                }
            }
            .badge("!")
            .tabItem {
                Image(systemName: "gear")
                Text("设置")
            }
            .tag(2)
        }
        .tint(Color.purple)
    }
}

struct MainView: View {
    @Binding var selectedTab: Int
    var body: some View {
        var body: some View {
        VStack {
            Text("首页")
                .font(.title)
                .fontWeight(.semibold)
            Button(action: {
                selectedTab = 2
            }, label: {
                Text("切换到setting tab")
                    .foregroundColor(.white)
                    .font(.headline)
                    .padding()
                    .background(Color.purple.cornerRadius(10))
            })
          }
        }
    }
}

TabView 的另一种形态

在SwiftUI中tabView有另一种形式的存在,就如我们平时看到的图片左右切换控价一样。它可以左右滑动来切换内容,代码和之前相差无几。但是效果却差别很大,只需要把TabViewSample里面的代码改成如下即可。注意的是我们设置了**.tabViewStyle(.page)**

struct TabView2Sample: View {
    
    @State var selectedTab: Int = 0
    
    var body: some View {
        ZStack {
            Color.yellow
                .edgesIgnoringSafeArea(.all)
            
            TabView(selection: $selectedTab) {
                MainView(selectedTab: $selectedTab)
                    .tag(0)
                
                Text("📚大全")
                    .tag(1)
                
                Text("设置")
                    .tag(2)
            }
            .tabViewStyle(.page)
        }
    }
}

效果如下:

22222.gif

大家有什么看法呢?欢迎留言讨论。
公众号:RobotPBQ