SwiftUI:更改基于NavigationBarTitle的TabbedView标签的更好方法

时间:2019-06-12 00:06:50

标签: swift swiftui

最终能够根据NavigationView中的当前标签使用TabbedView来更改onAppear()的标题,但是我我很确定这不是解决之道:

struct SomeTabbedView : View {
  @State private var selection = 0
  @State private var title = "First"
  var body: some View {
    NavigationView {
      TabbedView(selection: $selection) {
        ContentView()
          .tabItemLabel(
            Text("First")
          ).tag(0).onAppear{
            self.title = "First"
        }

        OtherView()
          .tabItemLabel(
            Text("Second")
          ).tag(1).onAppear{
            self.title = "Second"
          }
        }.navigationBarTitle(Text(title))
      }
    }
}
简而言之,这严重违反了DRY原理。如果我们决定更改第一个视图,例如字符串“ First”,则当前的实现将需要在三个不同的位置重复该视图。

我考虑初始化一个字典数组并在View: Label对上循环,但不仅我不确定这是正确的方法,而且我不确定如何继续执行它。也可以只包含一个带有标签的数组,但是如果我们想更改视图的顺序,则会造成另一个违规。

2 个答案:

答案 0 :(得分:4)

您的顶级视图应为TabbedView,并且每个选项卡都应具有自己的NavigationView。这并不能解决.navigationBarTitle.tabItemLabel都使用“ First”这一事实,但是实际上这是两个不同的事物,可以有所不同。

struct SomeTabbedView : View {
    @State private var selection = 0

    var body: some View {

        TabbedView(selection: $selection) {
            NavigationView {
                ContentView()
                    .navigationBarTitle(Text("First"))
            }
            .tabItemLabel(Text("First"))
            .tag(0)

            NavigationView {
                OtherView()
                    .navigationBarTitle(Text("Second"))
            }
            .tabItemLabel(Text("Second"))
            .tag(1)
        }.edgesIgnoringSafeArea(.top)
    }
}

答案 1 :(得分:0)

我遇到了类似的问题,并通过创建类似于SwiftUI的视图包装器解决了该问题。 这基本上只是在vacawama's answer中添加DRYness:

struct NavigationTab<Title, Content>: View where Title: StringProtocol, Content: View {
    var title: Title
    var content: () -> Content

    var body: some View {
        NavigationView {
            content()
                .navigationBarTitle(Text(title))
        }
        .tabItemLabel(Text(title))
    }
}

我将标记省略了,因为对我而言,在父视图中定义标记更有意义。您可以像这样使用它:

struct SomeTabbedView: View {
    @State private var selection = 0

    var body: some View {
        TabbedView(selection: $selection) {
            NavigationTab(title: "First") {
                ContentView()
            }
            .tag(0)

            NavigationTab(title: "Second") {
                OtherView()
            }
            .tag(1)
        }
    }
}

如果您要在选项卡标签上方添加图像之类的其他详细信息,这显然会变得更加复杂,因为.navigationBarTitle()需要一个Text实例。