如何为此自定义全屏模式设置实现@EnvironmentObject?

时间:2020-03-25 17:26:13

标签: modal-dialog swiftui environment tabview

我的目标是在根视图(本质上是选项卡式视图)上提供自定义模态。因此,我将TabView包裹在ZStack中,并且正在使用ObservableOBject。但是我不觉得我做对了。

在我的另一个文件中,我有一个自定义模式“子视图”,它也有一个枚举,我认为这是正确的方法。但是我无法弄清楚在看到模态后如何解散。

它必须是@EnvironmentObject,但我不知道是否要在场景委托中放入任何内容,等等。(“ Swift破解”使我失望,尽管这是一个很好的资源。)

我的想法是,选项卡式视图中的视图将具有各种按钮,这些按钮呈现不同的模式视图,稍后填充特定于用户的数据和用于输入数据的字段集。

现在,我只想了解如何展示和消除它们。

这是我的根视图

import SwiftUI

struct ContentView: View {

    @ObservedObject var modal = CustomModal()

    var body: some View {

        ZStack {
            TabView {
                ZStack {
                Color.pink.opacity(0.2)
                        Button(action: {
                            withAnimation{
                                self.modal.visibleModal = VisibleModal.circle
                            }
                        }) {
                            Text("Circle").font(.headline)
                        }
                        .frame(width: 270, height: 64)
                        .background(Color.pink.opacity(0.5)).foregroundColor(.white)
                        .cornerRadius(12)
                }
                   .tabItem{
                       VStack{
                       Image(systemName: "1.square.fill")
                       Text("One")
                       }
                    }.tag(1)

                   ZStack {
                   Color.blue.opacity(0.2)
                       Button(action: {
                        self.modal.visibleModal = VisibleModal.squircle
                       }) {
                           Text("Square").font(.headline)
                       }
                       .frame(width: 270, height: 64)
                       .background(Color.blue.opacity(0.5)).foregroundColor(.white)
                       .cornerRadius(12)
                       }
                   .tabItem{
                          VStack{
                          Image(systemName: "2.square.fill")
                          Text("Two")
                          }
                       }.tag(2)
               }.accentColor(.purple)
            VStack {
              containedView()
            }
        }
    }

    func containedView() -> AnyView {
        switch modal.visibleModal {
           case .circle: return AnyView(CircleView())
           case .squircle: return AnyView(SquircleView())
           case .none: return AnyView(Text(""))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这是我的第二个文件,其中包含枚举和“ subview”模式

import SwiftUI

class CustomModal: ObservableObject {
    @Published var visibleModal: VisibleModal = VisibleModal.none
}

enum VisibleModal {
    case circle, squircle, none
}

struct CircleView: View {
    var body: some View {
        ZStack {
            Color.pink.blur(radius: 0.4)
            Circle().fill()
            .frame(width: 300)
                .foregroundColor(Color.white.opacity(0.75))
            dismissButton()
        }.edgesIgnoringSafeArea(.all)
    }
}

struct SquircleView: View {
    var body: some View {
        ZStack{
            Color.green.blur(radius: 0.4)
            RoundedRectangle(cornerRadius: 48, style: .continuous)
                .frame(width: 300, height: 300).foregroundColor(Color.white.opacity(0.75))
            dismissButton()
        }.edgesIgnoringSafeArea(.all)
    }
}

struct dismissButton: View {

    @ObservedObject var modal = CustomModal()

    var body: some View {
        VStack{
            Spacer()
            Button(action: {
                self.modal.visibleModal = VisibleModal.none

            }) {
                Text("Dismiss").font(.headline)
            }
            .frame(width: 270, height: 64)
            .background(Color.white.opacity(0.35)).foregroundColor(.white)
            .cornerRadius(12)
            .padding(.bottom, 44)
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您只是想将可观察对象传递给新视图吗?

func containedView() -> some View {
        switch modal.visibleModal {
           case .circle: return CircleView()
                    .environmentObject(self.modal)
           case .squircle: return SquircleView()
                    .environmentObject(self.modal)
           case .none: return Text("")
        }
    }

除非我对这个问题有误解。

答案 1 :(得分:0)

好吧,经过很多摆弄后,它可以工作了。

现在我的代码如下。

根视图

struct ContentView: View {

    @EnvironmentObject var isModalVisible: CustomModal
    @ObservedObject var modal = CustomModal()

    var body: some View {

        ZStack {
            TabView {
                ZStack {
                Color.pink.opacity(0.2)
                        Button(action: {
                            withAnimation{
                                self.isModalVisible.isModalVisible.toggle()
                                self.modal.currentModal = VisibleModal.circle
                            }
                        }) {
                            Text("Circle").font(.headline)
                        }
                        .frame(width: 270, height: 64)
                        .background(Color.pink.opacity(0.5)).foregroundColor(.white)
                        .cornerRadius(12)
                }
                   .tabItem{
                       VStack{
                       Image(systemName: "1.square.fill")
                       Text("One")
                       }
                    }.tag(1)
                   ZStack {
                   Color.blue.opacity(0.2)
                       Button(action: {
                        self.isModalVisible.isModalVisible.toggle()
                        self.modal.currentModal = VisibleModal.squircle
                       }) {
                           Text("Square").font(.headline)
                       }
                       .frame(width: 270, height: 64)
                       .background(Color.blue.opacity(0.5)).foregroundColor(.white)
                       .cornerRadius(12)
                       }
                   .tabItem{
                          VStack{
                          Image(systemName: "2.square.fill")
                          Text("Two")
                          }
                       }.tag(2)
               }.accentColor(.purple)
            if self.isModalVisible.isModalVisible {
                VStack {
                  containedView()
                }
            }
        }
    }

    func containedView() -> AnyView {
        switch modal.currentModal {
           case .circle: return AnyView(CircleView())
           case .squircle: return AnyView(SquircleView())
           case .none: return AnyView(Text(""))
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(CustomModal())
    }
}


,第二个文件带有支持的视图,类和枚举:

import SwiftUI

class CustomModal: ObservableObject {
    @Published var isModalVisible = false
    @Published var currentModal: VisibleModal = .none
}

enum VisibleModal {
    case circle, squircle, none
}

struct CircleView: View {
    @EnvironmentObject var env: CustomModal

    var body: some View {
        ZStack {
            Color.pink.blur(radius: 0.4)
            Circle().fill()
            .frame(width: 300)
                .foregroundColor(Color.white.opacity(0.75))
            dismissButton()
        }.edgesIgnoringSafeArea(.all)
    }
}

struct SquircleView: View {
    var body: some View {
        ZStack{
            Color.green.blur(radius: 0.4)
            RoundedRectangle(cornerRadius: 48, style: .continuous)
                .frame(width: 300, height: 300).foregroundColor(Color.white.opacity(0.75))
            dismissButton()
        }.edgesIgnoringSafeArea(.all)
    }
}

struct dismissButton: View {

    @EnvironmentObject var env: CustomModal

    var body: some View {
        VStack{
            Spacer()
            Button(action: {
                self.env.isModalVisible.toggle()
                print("TAPPED")
            }) {
                Text("Dismiss").font(.headline)
            }
            .frame(width: 270, height: 64)
            .background(Color.white.opacity(0.35)).foregroundColor(.white)
            .cornerRadius(12)
            .padding(.bottom, 44)
        }
    }
}

它仍然可以重构。我确定。我也很高兴听到任何有关如何改进它的评论。但这似乎可行。

注意:此代码ContentView().environmentObject(CustomModal())放在PreviewP {rovider代码和SceneDelegate中。