1

我正在尝试构建一个可重复使用的入职寻呼机覆盖。所以我想TabView根据变量将不同的“幻灯片”传递给寻呼机IntroType。但是,既然TabView在没有任何容器的情况下直接获取内容,那么它的返回类型是什么?

这就是我希望它起作用的方式:

struct IntroViewTabPageTest: View {
    // MARK: Variables
    @Binding var isPresented: Bool
    @State var activeSlide: Int = 0
    var introType: IntroType
    
    // MARK: UI
    var body: some View {
        ZStack(alignment: .bottom) {
            Color.darkGalaxy
            
            TabView(selection: $activeSlide) {
                getContentBasedOnType() // <---- Content here
            }
            .tabViewStyle(.page)
            .indexViewStyle(.page(backgroundDisplayMode: .always))
        }
    }
    
    // MARK: Functions
    private func getContentBasedOnType() -> some View {
        switch (introType) {
        case .Main:
            return introContentMain
        case .SA:
            return introContentSA
        case .Journey:
            return introContentJourney
        }
    }
}

// Static content blocks for each type
extension IntroViewTabPageTest {

    // ----> Of course everywhere errors here, "some View" is not the right return type;
    // But what is it?

    private var introContentMain: some View {
        MainIntroSlide1()
        TextSlide(headline: "Headline", text: "Text")
    }
    
    private var introContentSA: some View {
        TextSlide(headline: "Headline", text: "Text")
        TextSlide(headline: "Headline2", text: "Text2")
        TextSlide(headline: "Headline3", text: "Text3")
    }
    
    private var introContentJourney: some View {
        TextSlide(headline: "Headline", text: "Text")
    }
}

enum IntroType: String {
    case Main, SA, Journey
}

struct IntroViewTabPageTest_Previews: PreviewProvider {
    static var previews: some View {
        IntroViewTabPageTest(isPresented: .constant(true), introType: .Main)
    }
}


另一种方法是让扩展中的每个变量都返回一个整体TabView,但这非常难看,我也没有完全弄清楚,仍然会在该路线上遇到一些其他错误。

我认为必须有某种方法可以做到这一点,我只是对 SwiftUI 的可用工具还不够了解。我可以想象一个带有 @ViewBuilder 包装器的函数可以在这里使用,但到目前为止我还没有完全理解它背后的逻辑。

我最接近的是使用幻灯片的一组 AnyView() 向下转换,但这使得使用 ForEach 很难并删除了类型。

4

2 回答 2

3

您可以像这样传递内容:

    import SwiftUI

    struct IntroViewTabPageTest<Content: View>: View {
  
      let content: Content
  
      init(@ViewBuilder content: () -> Content) {
        self.content = content()
      }
  
      var body: some View {
        ZStack(alignment: .bottom) {
          Color.gray
      
          TabView() {
            self.content
          }
          .tabViewStyle(.page)
          .indexViewStyle(.page(backgroundDisplayMode: .always))
        }
      }
  
    }

    struct IntroViewTabPageTest_Previews: PreviewProvider {
      static var previews: some View {
        Group {
      
          IntroViewTabPageTest {
            Text("hello 1")
            Text("hello 2")
          }
      
          IntroViewTabPageTest {
            Rectangle()
              .fill(Color.green)
              .frame(width: 100, height: 100)
          }
      
        }
      }
    }

于 2021-12-23T11:52:15.440 回答
1

在@Chris 的帮助下,我使它的工作如下:

import SwiftUI


struct IntroView: View {
    @Binding var isPresented: Bool
    var introType: IntroType

    var body: some View {
        if (introType == .Main) {
            getContentMain()
        }
        else if (introType == .SA) {
            getContentSA()
        }
        else if (introType == .Journey) {
            getContentJourney()
        }
    }
}

fileprivate struct IntroTabView<Content: View>: View {
    let content: Content
    @Binding var isPresented: Bool
    @State var activeSlide: Int = 0
    let slideAmount: Int
    
    init(isPresented: Binding<Bool>, slideAmount: Int, @ViewBuilder content: () -> Content) {
        self._isPresented = isPresented
        self.slideAmount = slideAmount
        self.content = content()
    }
    
    var body: some View {
        ZStack(alignment: .bottom) {
            Color.darkGalaxy
            
            TabView(selection: $activeSlide) {
                self.content
            }
            .tabViewStyle(PageTabViewStyle())
            .indexViewStyle(.page(backgroundDisplayMode: .always))
            
            // Buttons
            HStack { ... }
            .padding(16)
        }
    }
}

// Static content blocks for each type
fileprivate extension IntroView {
    private func getContentMain() -> some View {
        IntroTabView(isPresented: $isPresented, slideAmount: 3) {
            MainIntroSlide1().tag(0)
            TextSlide(headline: "Headline", text: "Text").tag(1)
            TextSlide(headline: "Headline2", text: "Text2").tag(2)
        }
    }
    
    private func getContentSA() -> some View {
        IntroTabView(isPresented: $isPresented, slideAmount: 2) {
            TextSlide(headline: "Headline", text: "Text").tag(0)
            TextSlide(headline: "Headline2", text: "Text2").tag(1)
        }
    }
    
    private func getContentJourney() -> some View {
        IntroTabView(isPresented: $isPresented, slideAmount: 1) {
            TextSlide(headline: "Headline", text: "Text").tag(0)
        }
    }
}

enum IntroType: String {
    case Main, SA, Journey
}

struct IntroView_Previews: PreviewProvider {
    static var previews: some View {
        IntroView(isPresented: .constant(true), introType: .Main)
    }
}

产生了这个漂亮的视图:
在此处输入图像描述

于 2021-12-23T14:39:38.773 回答