SwiftUI에서 새로운 견해를 제시하십시오


11

버튼을 클릭하고 present modallyUIKit 과 같은 새로운보기를 제시하고 싶습니다 . 여기에 이미지 설명을 입력하십시오

" 시트를 사용하여 새보기를 표시하는 방법 "을 이미 보았지만 기본보기에 모달 시트로 첨부하고 싶지 않습니다.

그리고 나는 NavigationLink새로운보기를 원하지 않고 오래된보기에는 탐색 관계가 있기 때문에을 사용 하고 싶지 않습니다.

당신의 도움을 주셔서 감사합니다...


기본 뷰에 모달 시트로 첨부하지 않으려는 이유는 무엇입니까? 에서도 표준 방법입니다 UIKit. 특별한 이유가 있습니까?
Mojtaba Hosseini

내 생각을 설명하려고합니다. 문제가 있으면 수정하십시오.
CH Wing

앱은 3 가지보기, 1 : 로그인 페이지 2 : TableView 페이지 3 : TableDetail 페이지, TableView 페이지 및 TableDetail 페이지는 탐색 관계입니다. 로그인 후 TableView 페이지에 표시되면 TableView 페이지는 로그인 후 로그인 페이지와 아무 관련이 없습니다
CH Wing

그래서 당신은 그것이 fullscreen옳 아야합니까?
Mojtaba Hosseini

네! 난 원해fullscreen
CH Wing

답변:


12

모달을 표시하려면 (iOS 13 스타일)

당신 sheet은 스스로를 기각하는 능력을 가진 간단한 것이 필요 합니다.

struct ModalView: View {
    @Binding var presentedAsModal: Bool
    var body: some View {
        Button("dismiss") { self.presentedAsModal = false }
    }
}

그리고 다음과 같이 제시하십시오.

struct ContentView: View {
    @State var presentingModal = false

    var body: some View {
        Button("Present") { self.presentingModal = true }
        .sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) }
    }
}

참고 난을 통과 presentingModal하면 모달 자체를 해제 할 수 있지만, 당신이 그것을 제거 할 수 있도록 모달로.


그것을 fullscreen시각적으로 만 보여 주도록

에 액세스해야합니다 ViewController. 따라서 도우미 컨테이너와 환경 관련 요소가 필요합니다.

struct ViewControllerHolder {
    weak var value: UIViewController?
}

struct ViewControllerKey: EnvironmentKey {
    static var defaultValue: ViewControllerHolder {
        return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)

    }
}

extension EnvironmentValues {
    var viewController: UIViewController? {
        get { return self[ViewControllerKey.self].value }
        set { self[ViewControllerKey.self].value = newValue }
    }
}

그런 다음이 확장을 구현해야합니다.

extension UIViewController {
    func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
        toPresent.modalPresentationStyle = style
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        self.present(toPresent, animated: true, completion: nil)
    }
}

드디어

당신은 그것을 다음 fullscreen과 같이 만들 수 있습니다 :

struct ContentView: View {
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?

    var body: some View {
        Button("Login") {
            self.viewControllerHolder?.present(style: .fullScreen) {
                Text("Main") // Or any other view you like
            }
        }
    }
}

큰! 자세한 솔루션에 감사드립니다
CH Wing

환경 등록 정보 랩퍼에서이 오류가 발생합니다. 'Environment <UIViewController?>'유형의 값을 지정된 'UIViewController'유형으로 변환 할 수 없음
jsbeginnerNodeJS

기본적으로 처리해야하지만 ?줄 끝에 추가 하십시오. @jsbeginnerNodeJS
Hosseini

나는 콘솔에서이 오류가 발생합니다 :```경고 : 현재 <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_ : 0x7fafd2641d30>에 시도를 <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_ : 0x7fafd2611bd0>에 그보기 창 계층 구조가 아닌```!
jsbeginnerNodeJS

어떻게 해고합니까?
gabrielapittari

0

간단한 일방 통행보기입니다. 매우 간단합니다.

        struct ChildView: View{
           private  let colors: [Color] = [.red, .yellow,.green,.white]
           @Binding var index : Int
           var body: some View {
           let next = (self.index+1)  % MyContainer.totalChildren
             return   ZStack{
                    colors[self.index  % colors.count]
                     Button("myNextView \(next)   ", action: {
                    withAnimation{
                        self.index = next
                    }
                    }
                )}.transition(.asymmetric(insertion: .move(edge: .trailing)  , removal:  .move(edge: .leading)  ))
            }
        }

        struct MyContainer: View {
            static var totalChildren = 10
            @State private var value: Int = 0
            var body: some View {
                    HStack{
                        ForEach(0..<(Self.totalChildren) ) { index in
                            Group{
                            if    index == self.value {
                                ChildView(index:  self.$value)
                                }}
                            }
                }
                }
        }

-1

면책 조항 : 아래는 실제로 "네이티브 모달"과 같지 않으며, 행동하거나 룩앤필하지도 않지만, 누군가가 하나의 뷰를 다른 뷰보다 커스텀 전환하여 활성화하고 최상위 뷰 만 활성화 해야하는 경우 다음 접근법이 도움이 될 수 있습니다.

따라서 다음과 같은 것을 기대하면

커스텀 SwiftUI 모달

다음은 접근법을 데모하기위한 간단한 코드입니다 (코즈 애니메이션 및 전환 매개 변수는 원하는대로 변경할 수 있음)

struct ModalView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = false
                }
            }) {
                Text("Hide modal")
            }
            Text("Modal View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.green)
    }
}

struct MainView : View {
    @Binding var activeModal: Bool
    var body : some View {
        VStack {
            Button(action: {
                withAnimation(.easeInOut(duration: 0.3)) {
                    self.activeModal = true
                }
            }) {
                Text("Show modal")
            }
            Text("Main View")
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
        .background(Color.yellow)
    }
}

struct ModalContainer: View {
    @State var showingModal = false
    var body: some View {
        ZStack {
            MainView(activeModal: $showingModal)
                .allowsHitTesting(!showingModal)
            if showingModal {
                ModalView(activeModal: $showingModal)
                    .transition(.move(edge: .bottom))
                    .zIndex(1)
            }
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.