SwiftUI - PresentationButton с модальным полноэкранным режимом - PullRequest
13 голосов
/ 25 июня 2019

Я пытаюсь реализовать кнопку, которая представляет другую сцену с анимацией «Слайд из Боттона».

PresentationButton выглядел как хороший кандидат, поэтому я попробовал:

import SwiftUI

struct ContentView : View {
    var body: some View {
        NavigationView {
            PresentationButton(destination: Green().frame(width: 1000.0)) {
                Text("Click")

                }.navigationBarTitle(Text("Navigation"))
        }
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .previewDevice("iPhone X")
                .colorScheme(.dark)

            ContentView()
                .colorScheme(.dark)
                .previewDevice("iPad Pro (12.9-inch) (3rd generation)"

            )

        }

    }
}
#endif

А вот и результат: enter image description here

Я хочу, чтобы зелёный вид покрывал весь экран, а также чтобы модал не "перетаскивался до закрытия".

Можно ли добавить модификатор PresentationButton, чтобы сделать его полноэкранным, а не перетаскиваемым?

Я также попробовал навигационную кнопку, но: - Он не «скользит снизу» - Он создает «кнопку назад» в подробном представлении, который я не хочу

спасибо!

Ответы [ 2 ]

8 голосов
/ 04 июля 2019

Хотя мой другой ответ в настоящее время правильный, люди, вероятно, захотят сделать это сейчас.Мы можем использовать Environment для передачи контроллера представления детям. Суть здесь

struct ViewControllerHolder {
    weak var value: UIViewController?
}


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

extension EnvironmentValues {
    // This will get/set the view controller directly.  No need to worry about `.value` in use
    var viewController: UIViewController? {
        get { return self[ViewControllerKey.self].value }
        set { self[ViewControllerKey.self].value = newValue }
    }

}

Добавить расширение для UIViewController

extension UIViewController {
    func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) {
       // Must instantiate HostingController with some sort of view...
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
       ... but then we can reset that view to include the environment
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        self.present(toPresent, animated: true, completion: nil)
    }
}

И всякий раз, когда нам это нужно, используйте его:

struct MyView: View {

    @Environment(\.viewController) private var viewController: UIViewController?

    var body: some View {
        Button(action: {
           self.viewController?.present(style: .fullScreen) {
              MyView()
           }
        }) {
           Text("Present me!")
        }
    }
}
7 голосов
/ 02 июля 2019

К сожалению, начиная с Beta 2 Beta 3, это невозможно в чистом SwiftUI. Вы можете видеть, что Modal не имеет параметров для чего-либо вроде UIModalPresentationStyle.fullScreen. Аналогично для PresentationButton .

Я предлагаю подать радар.

Ближайшее, что вы можете сделать сейчас, это что-то вроде:

    @State var showModal: Bool = false
    var body: some View {
        NavigationView {
            Button(action: {
                self.showModal = true
            }) {
                Text("Tap me!")
            }
        }
        .navigationBarTitle(Text("Navigation!"))
        .overlay(self.showModal ? Color.green : nil)
    }

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

...