SwiftUI 中具有可变选项卡数量的自定义选项卡栏

can*_*boy 3 ios swift swiftui swiftui-tabview

我正在尝试复制 iPad 版 Safari 中的选项卡栏,如下所示:

在此输入图像描述

(有没有第三方库可以做到这一点?我找不到)

我正在使用下面的代码。结果是这样的:

在此输入图像描述

我想我需要以某种方式将视图转换为数组,并有一个按钮(在选项卡或页面上)来添加和删除选项卡。知道如何做到这一点吗?

import SwiftUI

struct TabLabel : View {

      var text : String
      var imageName : String
      var color : Color

      var body : some View {
            VStack() {
                  Image(systemName: imageName)
                  Text(text).font(.caption)
            }.foregroundColor(color)
      }
}

struct TabButton : View {
      @Binding var currentSelection : Int
      var selectionIndex : Int
      var label : TabLabel

      var body : some View {
            Button(action: { self.currentSelection = self.selectionIndex }) { label }.opacity(selectionIndex == currentSelection ? 0.5 : 1.0)
      }
}

struct CustomTabBarView<SomeView1 : View, SomeView2 : View, SomeView3 : View> : View {


      var view1 : SomeView1
      var view2 : SomeView2
      var view3 : SomeView3

      @State var currentSelection : Int = 1
      var body : some View {

            let label1 = TabLabel(text: "First", imageName:  "1.square.fill", color: Color.red)
            let label2 = TabLabel(text: "Second", imageName:  "2.square.fill", color: Color.purple)
            let label3 = TabLabel(text: "Third", imageName:  "3.square.fill", color: Color.blue)

            let button1 = TabButton(currentSelection: $currentSelection, selectionIndex: 1, label: label1)
            let button2 = TabButton(currentSelection: $currentSelection, selectionIndex: 2, label: label2)
            let button3 = TabButton(currentSelection: $currentSelection, selectionIndex: 3, label: label3)


            return VStack() {
                
                HStack() {
                      button1
                      Spacer()
                      button2
                      Spacer()
                      button3

                }.padding(.horizontal, 48)
                      .frame(height: 48.0)
                      .background(Color(UIColor.systemGroupedBackground))
                
                  Spacer()

                  if currentSelection == 1 {
                        view1
                  }
                  else if currentSelection == 2 {
                        view2
                  }
                  else if currentSelection == 3 {
                        view3
                  }

                  Spacer()

                  
            }

      }
}



struct ContentView: View {
    @State private var showGreeting = true
    var body: some View {
        
                let view1 = VStack() {
                      Text("The First Tab").font(.headline)
                      Image(systemName: "triangle").resizable().aspectRatio(contentMode: .fit).frame(width: 100)
                }

                let view2 = Text("Another Tab").font(.headline)
                let view3 = Text("The Final Tab").font(.headline)

                return CustomTabBarView(view1: view1, view2: view2, view3: view3)
          }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*man 6

与 SwiftUI 的许多问题一样,这似乎过于复杂,因为您将状态的概念与该状态在屏幕上的绘制方式混合在一起。

\n

暂时删除视觉效果,您所拥有的数据是:

\n
    \n
  • 有序的页面集合,每个页面都有标题和图像
  • \n
  • 该集合中哪个页面处于活动状态的概念
  • \n
\n

(请注意,我在这里将它们称为“页面”,以尝试将它们作为选项卡与视觉表示分开。)

\n

您还可以执行一些操作来更改该数据:

\n
    \n
  • 您的用户可以选择哪个页面应该是活动页面
  • \n
  • 他们可以向集合中添加新页面
  • \n
  • 他们可以从集合中删除现有页面
  • \n
\n

现在,如果您将这些小步骤视为您的数据模型,则可以构建一个或多个对象来干净地封装它。

\n

然后,您可以继续确定 SwiftUI 如何表示该数据以及它如何包含操作触发器。例如:

\n
    \n
  • 水平选项卡列表循环遍历有序的页面集合并呈现每个页面
  • \n
  • 每个选项卡都有一个按钮操作,点击该操作后,将该按钮设置为活动按钮
  • \n
  • 每个选项卡都有一个关闭按钮,点击该按钮后,会将其从页面集合中删除
  • \n
  • 点击单独的按钮后,可以将新页面添加到集合中
  • \n
\n

等等。希望您可以看到 SwiftUI 中的每个视图现在都有特定的用途,并且应该更容易让您思考。

\n

您甚至可能决定使用不同的 UI \xe2\x80\x93,List例如,您可以在 中垂直列出页面,或者像 iPhone 的 Safari 页面视图一样在网格中列出页面。但即使您这样做了,您的基础数据也不会改变。

\n