SwiftUI view injection into other view

北慕城南 提交于 2021-01-29 14:42:06

问题


I want to create such view hierarchy

ZStack {
  TabView {
    NavigationView {
      NavigationLink ... {
        Subview()
      }
    }
  }
  FullScreenView()
} 

inside subview there is button which toogles environment variable to present full screen view like in this example: https://github.com/nikishovde/HideTabBarInSubview how to inject subview contents to full screen view when showFullscreen variable is toggled true ? ( I want to make FullScreenView generic so I can use it for different views which I want to present on full screen)

edited: added code

struct FullScreen: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        VStack {
            Text("INSERT SlidesView() here ...")
        }
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        .background(Color.red)
    }
}

struct SlidesView: View {
    @EnvironmentObject var userData: UserData

    var slidesURL: String

    var body: some View {
        ZStack(alignment: .topTrailing) {
            Webview(url: slidesURL).padding(5)
            Button(action: {
                self.userData.showFullScreen.toggle()

            }) {
                Image(systemName: "arrow.up.left.and.arrow.down.right")
                    .padding(10)
                    .background(Color.white)
                    .clipShape(RoundedRectangle(cornerRadius: 10))
                    .offset(x: 10, y: 10)
                    .padding(10)
                    .foregroundColor(.blue)
            }
            .navigationBarTitle("test")
        }
    }
}

struct AppView: View {
    @EnvironmentObject var userData: UserData

    @ObservedObject var auth = Auth.shared

    var body: some View {
        ZStack {
            Group {
                if self.auth.authToken != nil && !self.firstLaunch {
                    TabView {
                          ViewWithNavigationView().environmentObject(self.userData)
                            .tabItem {
                                Image(systemName: "tv")
                                Text(verbatim: "Talks")
                        }.tag(0)
                    }
                } else {
                    // TODO: 2020-03-06 - Create better onboarding screen
                    VStack(spacing: 20) {
                        Text("Hello!").font(.largeTitle)
                        Text("I prepare Code Conf App for your first use.")

                        // FIXME: 2020-03-06 - Disable button after first tap and add spinner as loading indicator
                        Button(action: {
                            self.firstLaunch.toggle()
                            UserDefaultsConfig.firstLaunch = self.firstLaunch
                        }) {
                            Text("OK")
                        }
                    }
                }
                if self.userData.showFullScreen {
                    FullScreen().environmentObject(self.userData)

                }
            }
        }
    }
}

final class UserData: ObservableObject {

    @Published var showFullScreen = false
}

回答1:


Here is a demo of possible approach (used simplified part of your code as not all dependencies provided). Tested with Xcode 11.4 / iOS 13.4

class FullScreenData: ObservableObject {
    @Published var originalView: (() -> AnyView)? = nil
}

struct FullScreenView: View {
    @EnvironmentObject var fullScreenData: FullScreenData

    var body: some View {
        Group {
            if fullScreenData.originalView != nil {
                fullScreenData.originalView!()
                    .edgesIgnoringSafeArea(.all)
            } else {
                EmptyView()
            }
        }
    }
}

struct SlidesView: View {
    @EnvironmentObject var fullScreenData: FullScreenData

    var body: some View {
        ZStack(alignment: .topTrailing) {
            Rectangle()                  // demo placeholder
                .fill(Color.yellow).border(Color.red)
            Button(action: {
                self.fullScreenData.originalView =
                    self.fullScreenData.originalView == nil ? { AnyView(self) } : nil
            }) {
                Image(systemName: "arrow.up.left.and.arrow.down.right")
                    .padding(10)
                    .background(Color.white)
                    .clipShape(RoundedRectangle(cornerRadius: 10))
                    .offset(x: 10, y: 10)
                    .padding(10)
                    .foregroundColor(.blue)
            }
            .navigationBarTitle("test")
        }
    }
}

struct TestFullScreen: View {
    @EnvironmentObject var fullScreenData: FullScreenData
    var body: some View {
        ZStack {
          TabView {
            NavigationView {
              NavigationLink(destination: Text("Destination")) {
                SlidesView()
              }
            }.tabItem {
                Image(systemName: "1.circle")
            }
          }
          FullScreenView()
        }
    }
}

struct TestFullScreen_Previews: PreviewProvider {
    static var previews: some View {
        TestFullScreen().environmentObject(FullScreenData())
    }
}


来源:https://stackoverflow.com/questions/61518368/swiftui-view-injection-into-other-view

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!