Sajikan tampilan baru di SwiftUI

11

Saya ingin mengklik tombol dan kemudian menyajikan tampilan baru seperti present modallydi UIKit masukkan deskripsi gambar di sini

Saya sudah melihat " Cara menyajikan tampilan baru menggunakan lembar ", tapi saya tidak ingin melampirkannya ke tampilan utama sebagai lembar modal.

Dan saya tidak ingin menggunakan NavigationLink, karena saya tidak ingin tampilan baru dan tampilan lama memiliki hubungan navigasi.

Terima kasih atas bantuan Anda...

CH Wing
sumber
Mengapa Anda tidak ingin melampirkannya ke tampilan utama sebagai lembar modal? Ini adalah metode standar bahkan di UIKit. Apakah Anda punya alasan khusus?
Mojtaba Hosseini
Saya mencoba menjelaskan pikiran saya ... Jika ada yang salah, tolong perbaiki saya.
CH Wing
Aplikasi memiliki 3 tampilan, 1: Halaman Masuk 2: TableView Halaman 3: Halaman TableDetail, halaman TableView dan TableDetail adalah relasi navigasi. Setelah login akan ditampilkan pada halaman TableView, halaman TableView tidak memiliki hubungan dengan halaman login setelah login
CH Wing
Jadi, Anda perlu fullscreenbenar?
Mojtaba Hosseini
ys! saya inginfullscreen
CH Wing

Jawaban:

12

Untuk menunjukkan modal (gaya iOS 13)

Anda hanya perlu yang sederhana sheetdengan kemampuan untuk menolak sendiri:

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

Dan menyajikannya seperti:

struct ContentView: View {
    @State var presentingModal = false

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

Perhatikan bahwa saya meneruskan presentingModalke modal sehingga Anda dapat mengabaikannya dari modal itu sendiri, tetapi Anda dapat menyingkirkannya.


Untuk membuatnya benar-benar hadir fullscreen(Tidak hanya secara visual)

Anda perlu mengakses ViewController. Jadi, Anda memerlukan beberapa wadah pembantu dan hal-hal lingkungan:

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

Maka Anda harus menggunakan implement ekstensi ini:

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

Akhirnya

Anda bisa membuatnya fullscreenseperti:

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
            }
        }
    }
}
Mojtaba Hosseini
sumber
Bagus! terima kasih atas solusi terperinci Anda
CH Wing
Saya mendapatkan kesalahan ini di pembungkus properti lingkungan: Tidak dapat mengonversi nilai jenis 'Lingkungan <UIViewController?>'
Ke
Ini harus ditangani secara default, tetapi coba tambahkan ?di akhir baris di sana. @jsbeginnerNodeJS
Mojtaba Hosseini
Saya mendapatkan error ini di konsol: `` `Peringatan: Mencoba untuk hadir <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fafd2641d30> pada <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fafd2611bd0> yang pandangannya tidak dalam hirarki jendela` ``!
jsbeginnerNodeJS
bagaimana Anda mengabaikannya?
gabrielapittari
0

Berikut ini adalah pandangan satu arah yang sederhana. Sangat lurus ke depan.

        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)
                                }}
                            }
                }
                }
        }
E.Com
sumber
-1

Penafian: Di bawah ini tidak benar-benar seperti "modal asli", tidak berperilaku atau melihat & merasakan, tetapi jika ada orang yang membutuhkan transisi khusus dari satu pandangan ke pandangan lainnya, menjadikan hanya yang aktif di atas, pendekatan berikut mungkin bisa membantu.

Jadi, jika Anda mengharapkan sesuatu seperti berikut ini

modal SwiftUI khusus

Berikut ini adalah kode sederhana untuk demo pendekatannya (dari animasi corse & parameter transisi dapat diubah sesuai keinginan)

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