代码之家  ›  专栏  ›  技术社区  ›  Big_Chair

SwiftUI-通过函数传入TabView的内容

  •  0
  • Big_Chair  · 技术社区  · 4 年前

    我试图建立一个可重复使用的登机寻呼机覆盖。所以我想把不同的“幻灯片”传给传呼机 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变得很困难,并且删除了类型。

    0 回复  |  直到 4 年前
        1
  •  3
  •   Chris    4 年前

    你可以这样传递内容:

        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)
              }
          
            }
          }
        }
    
    
        2
  •  1
  •   Big_Chair    4 年前

    在@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)
        }
    }
    
    

    这是一个不错的景观:
    enter image description here