นำเสนอมุมมองใหม่ใน SwiftUI


11

ฉันต้องการคลิกปุ่มจากนั้นนำเสนอมุมมองใหม่เหมือนpresent modallyใน UIKit ป้อนคำอธิบายรูปภาพที่นี่

ฉันเคยเห็น " วิธีการนำเสนอมุมมองใหม่โดยใช้ชีต" แต่ฉันไม่ต้องการแนบกับมุมมองหลักเป็นแผ่นคำกริยา

และฉันไม่ต้องการใช้NavigationLinkเพราะฉันไม่ต้องการมุมมองใหม่และมุมมองเก่ามีความสัมพันธ์ในการนำทาง

ขอบคุณสำหรับความช่วยเหลือของคุณ...


ทำไมคุณไม่ต้องการแนบไปกับมุมมองหลักเป็นแผ่นคำกริยา? UIKitมันเป็นวิธีการมาตรฐานแม้จะอยู่ใน คุณมีเหตุผลพิเศษหรือไม่?
Mojtaba Hosseini

ฉันพยายามอธิบายความคิดของฉัน ... หากมีสิ่งใดผิดโปรดแก้ไขให้ถูกต้อง
CH Wing

แอพมีมุมมอง 3, 1: หน้าเข้าสู่ระบบ 2: TableView หน้า 3: หน้า TableDetail, หน้า TableView และหน้า TableDetail คือความสัมพันธ์ในการนำทาง หลังจากเข้าสู่ระบบจะนำเสนอไปยังหน้า TableView หน้า TableView ไม่มีความสัมพันธ์กับหน้าเข้าสู่ระบบหลังจากเข้าสู่ระบบ
CH Wing

ดังนั้นคุณต้องให้ถูกfullscreenต้องหรือไม่
Mojtaba Hosseini

ys! ฉันต้องการ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 }
    }
}

จากนั้นคุณควรใช้ implement ส่วนขยายนี้:

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

ฉันได้รับข้อผิดพลาดนี้ที่ wrapper คุณสมบัติของสภาพแวดล้อม: ไม่สามารถแปลงค่าประเภท 'Environment <UIViewController?>' เป็นประเภทที่ระบุ 'UIViewController'
jsbeginnerNodeJS

ควรจัดการโดยค่าเริ่มต้น แต่ลองเพิ่ม?ที่ท้ายบรรทัดนั้น @jsbeginnerNodeJS
Mojtaba 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

ข้อจำกัดความรับผิดชอบ:ด้านล่างไม่เหมือน "คำกริยาดั้งเดิม" ไม่ว่าจะเป็นพฤติกรรมหรือรูปลักษณ์ แต่ถ้าใครก็ตามต้องการการเปลี่ยนมุมมองหนึ่งแบบกำหนดเองมากกว่าการทำให้ใช้งานได้ดีอันดับแรกแนวทางต่อไปนี้อาจมีประโยชน์

ดังนั้นหากคุณคาดหวังสิ่งต่อไปนี้

Modal SwiftUI ที่กำหนดเอง

นี่คือรหัสง่ายๆสำหรับการสาธิตวิธีการ (ของพารามิเตอร์ภาพเคลื่อนไหวและการเปลี่ยนแปลง corse สามารถเปลี่ยนแปลงได้ตามความต้องการ)

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.