如何在SwiftUI中使用TabbedView?

时间:2019-06-25 06:37:54

标签: ios swift swiftui swift5 ios13

struct ContentView : View {
    var body: some View {
        NavigationView {
            TabbedView {
                PasswordGenerator()
                    .tabItemLabel {
                        Image("KeyGlyph")
                        Text("Generator")
                }

                PasswordGeneratorSettings()
                    .tabItemLabel {
                            Image("SettingsGlyph")
                            Text("Settings")
                }
            }
        }
    }
}

该代码无法编译,但已在WWDC的Swift Essentials视频中使用(请参阅第54:30分钟),我已经看到了一些变通方法,例如VStack变通方法(但即使有很多缺陷,左侧选项卡也是如此左边的标签太远,右边的标签太右边了,切换标签时,只有第一个最初加载的标签会加载,而另一个标签保持空白并且使用标签无济于事。那么,如何有两个用于加载视图并具有图像和文本的选项卡?

8 个答案:

答案 0 :(得分:2)

您的代码应该有效,但这是iOS & iPadOS 13 Beta 2 Release Notes中的一个已知问题:

  

tabItemLabel(_ :)修饰符不接受@ViewBuilder闭包。

在解决此问题之前,唯一的解决方法是使用您所说的VStack。

MyView()
    .tabItemLabel(VStack {
        Image("resourceName")
        Text("Item")
    })

更新:

此问题已通过 Xcode 11 beta 3 修复:

  

tabItemLabel( :)修饰符-现在名为tabItem( :)-现在接受   @ViewBuilder闭包。

示例:

.tabItem {
    Image(systemName: "circle")
    Text("Tab1")
}

答案 1 :(得分:2)

使用XCode beta 3,以下方法应该起作用:

import SwiftUI

struct Home : View {
    @State private var currentTab = 1

    var body: some View {
        TabbedView(selection: $currentTab) {
            FirstView()
                .tabItem {
                    VStack {
                        Image(systemName: "1.circle")
                        Text("First Tab")
                    }
                }.tag(1)
            SecondView()
                .tabItem {
                    VStack {
                        Image(systemName: "2.circle")
                        Text("Second Tab")
                    }
                }.tag(2)
        }
    }
}

不过,将标签标签包含在VStack中似乎是可选的。因此,您可以决定删除它,例如:

import SwiftUI

struct Home : View {
    @State private var currentTab = 1

    var body: some View {
        TabbedView(selection: $currentTab) {
            FirstView()
                .tabItem {
                    Image(systemName: "1.circle")
                    Text("First Tab")
                }.tag(1)
            SecondView()
                .tabItem {
                    Image(systemName: "2.circle")
                    Text("Second Tab")
                }.tag(2)
        }
    }
}

答案 2 :(得分:2)

对于那些仍在寻找方法的人,这是Xcode 11 GM的更新。

struct Tabs: View {

    @State private var selected = 0

    var body: some View {
        TabView(selection: $selected) {
            MyFirstView()
                .tabItem {
                    Image(systemName: (selected == 0 ? "star.fill" : "star"))
                    Text("One")
                }.tag(0)
            MySecondView()
                .tabItem {
                    Image(systemName: (selected == 1 ? "star.fill" : "star"))
                    Text("Two")
                }.tag(1)
            MyThirdView()
                .tabItem {
                    Image(systemName: (selected == 2 ? "star.fill" : "star"))
                    Text("Three")
                }.tag(2)
        }
        .edgesIgnoringSafeArea(.all) // Important if you want NavigationViews to go under the status bar...
    }
}

答案 3 :(得分:1)

TabbedView已弃用。

您现在可以改为使用 TabView

struct AppTabbedView: View {
    @State private var selection = 3

    var body: some View {
        TabView (selection:$selection){
            Text("The First Tab")
                .tabItem {
                    Image(systemName: "1.square.fill")
                    Text("First")

            }
            .tag(1)
            Text("Another Tab")
                .tabItem {
                    Image(systemName: "2.square.fill")
                    Text("Second")
            }.tag(2)
            Text("The Last Tab")
                .tabItem {
                    Image(systemName: "3.square.fill")
                    Text("Third")
            }.tag(3)
        }
        .font(.headline)
    }
}

答案 4 :(得分:1)

从Xcode 11 GM开始,此代码有效:(来自https://developer.apple.com/documentation/swiftui/tabview

TabView {
    Text("The First Tab")
        .tabItem {
            Image(systemName: "1.square.fill")
            Text("First")
        }
    Text("Another Tab")
        .tabItem {
            Image(systemName: "2.square.fill")
            Text("Second")
        }
    Text("The Last Tab")
        .tabItem {
            Image(systemName: "3.square.fill")
            Text("Third")
        }
}
.font(.headline)

答案 5 :(得分:1)

TabbedView已弃用,并已重命名为TabView 您可以像这样使用TabView

TabView {
    (Text("Tab 1!").tabItem {
         Text("First")
    })
    (Text("Tab 2!").tabItem {
         Text("Second")
    })
}

答案 6 :(得分:1)

TabbedView()已过时,请改用TabView()

使用整数选择视图对我来说很不好,从我使用UIButton和UIView的tag()开始,最好枚举您的工作,而不是分配范围很广的硬编码值。即Int.min()Int.max()。这也使代码将来更易于阅读和维护。

TabView(selection: )可用于选择索引,并声明为:

public struct TabView<SelectionValue, Content> : View where SelectionValue : Hashable, Content : View {
    public init(selection: Binding<SelectionValue>?, @ViewBuilder content: () -> Content)
…

这意味着您可以选择具有任何可散列内容的索引。

我们可以使用符合enum的{​​{1}}来包含选项卡列表, 这样可以在以后使用Observable来帮助控制和加载视图状态。或者将枚举作为应用程序状态的一部分。我确信您可以使用大量资源来找到满足您需求的合适解决方案。

Hashable

答案 7 :(得分:0)

“ TabbedView”的使用方式类似于以下内容:

    struct TabView : View {

        @State private var selection = 1

        var body: some View {
            TabbedView (selection: $selection) {
                InboxList()
                    .tabItemLabel(selection == 1 ? Image("second") : Image("first"))
                    .tag(1)

                PostsList()
                    .tabItemLabel(Image("first"))
                    .tag(2)

                Something()
                    .tabItemLabel(Image("first"))
                    .tag(3)
            }
        }
    }

我不确定为什么您的示例无法编译,但是您错过了每个“选项卡”上的selection参数和.tag属性。

在当前的XCode版本(测试版2)中,不能同时显示文本和图像作为标签。