如何像 UIKit 的 UIViewControllerTransitioningDelegate 一样呈现模态视图控制器?

How to present a modal view controller like with UIKit's UIViewControllerTransitioningDelegate?

我正在从 UIKit 切换到 SwiftUI,但仍然难以理解它的某些部分,尤其是视图之间的转换。

我有这样一种情况,屏幕上显示了一个带有列表的视图控制器,比如 ElementsListViewController(),当点击一个元素时,我想显示一个带有自定义 UI/animation 的模式:不透明叠加层会出现 alpha 值的动画,而白色模态“sheet”会从下到上出现。

这是它的样子:

使用 UIKit,我会使用 UIViewControllerAnimatedTransitioning 来做到这一点。

现在我想对 SwiftUI 做同样的事情,但我不知道该怎么做。

到目前为止我有这个:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ElementsList()
        }
    }
}

struct ElementsList: View {
    @State var elements: [String] = (0..<100).map { "Element #\([=10=])" }

    var body: some View {
        List(elements, id: \.self) {
            Text([=10=])
                .onTapGesture {
                    // what to do here to display ModalView as I want to?
                }
        }
        .listStyle(PlainListStyle())
    }
}

struct ModalView: View {
    var body: some View {
        ZStack {
            Color.black.opacity(0.8)
            Color.white
                .cornerRadius(20.0)
                .padding(.top, 150)
        }
        .ignoresSafeArea()
    }
}

我最好的选择是什么?感谢您的帮助

好吧,标准 .sheet 没有 built-in 这样的灵活性,但它可以非常快地实现自定义。

这是简单的演示 (Xcode 13.3 / iOS 15.4)

主要部分:

struct ElementsList: View {
// ...
        ModalView(isPresented: $isModal) {
            List(elements, id: \.self) {


struct ModalView<V: View>: View {
    @Binding var isPresented: Bool
// ...
        ZStack {
            content()
            ZStack {
                VStack {
                    if isPresented {
                        Color.black.opacity(0.8)
                            .transition(.opacity)
                    }
                }.animation(.easeInOut(duration: 0.25), value: isPresented)


Complete test code in project is here