Как мне реализовать @EnvironmentObject для этой пользовательской полноэкранной модальной настройки? - PullRequest
0 голосов
/ 25 марта 2020

Моя цель состоит в том, чтобы пользовательские модалы присутствовали над представлением root, которое по сути является представлением с вкладками. Итак, я обернул TabView в ZStack и использую ObservableOBject. Но я не чувствую, что делаю это правильно.

В моем другом файле у меня есть пользовательские модальные «подпредставления», в которых также есть перечисление, которое, я думаю, является правильным подходом. Но я не могу понять, как отклонить модал после того, как он виден.

Это должен быть @EnvironmentObject, но я не знаю, что, если что-то добавить в делегат сцены, et c. («Взлом с помощью Swift» подводит меня здесь, хотя это отличный ресурс.)

Моя идея состоит в том, что представления в представлении с вкладками будут иметь различные кнопки, которые представляют разные модальные представления, позже заполненные данными, указанными c сказать пользователю и набор полей для ввода данных.

Прямо сейчас я просто хочу понять, как представить и отклонить их.

Вот мой root просмотр

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

А вот и мой второй файл с модальностями enum и "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 голосов
/ 26 марта 2020

Ладно, после долгих потрясений все работает.

Теперь мой код выглядит следующим образом.

Root view

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.

0 голосов
/ 25 марта 2020

Вы просто пытаетесь передать свой наблюдаемый объект в новое представление?

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

Если только я неправильно понимаю вопрос.

...