【问题标题】:How do I implement @EnvironmentObject for this custom full-screen modal setup?如何为此自定义全屏模式设置实现 @EnvironmentObject?
【发布时间】:2020-07-06 07:25:18
【问题描述】:

我的目标是在本质上是选项卡式视图的根视图上显示自定义模式。因此,我将 TabView 包装在 ZStack 中并使用 ObservableOBject。但我不觉得我的做法是正确的。

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

它必须是@EnvironmentObject,但我不知道是否可以在场景委托等中添加任何内容(“Hacking with 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()
    }
}

这是我的第二个包含枚举和“子视图”模态的文件

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

【问题讨论】:

    标签: modal-dialog swiftui environment tabview


    【解决方案1】:

    好的,经过大量的摆弄,它可以工作了。

    现在我的代码如下。

    根视图

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

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

    注意:此代码 ContentView().environmentObject(CustomModal()) 放在 previewP{提供者代码和 SceneDelegate 中。

    【讨论】:

    • 我注意到在物理设备上,TabView ZStack 中的Color.pink.opacity(0.2) 不能正确切换。任何路过这里的人都知道为什么吗?
    【解决方案2】:

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

    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("")
            }
        }
    

    除非我误解了这个问题。

    【讨论】:

    • 我不确定你的代码是做什么的。当我插入.environmentObject(self.modal) 行时,Xcode 告诉我添加as! AnyView,但是当我运行它时,它会因Could not cast value of type 而崩溃。我当前的代码正确显示了模态。但我无法弄清楚在模态视图上的关闭按钮中放置什么来关闭它。我可能也需要按钮中的一些参数?
    • 快速提问为什么 AnyView 而不是 containsView() 返回一些视图?
    • 我在这里的答案中找到了:stackoverflow.com/questions/56736466/…
    猜你喜欢
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多