【问题标题】:SwiftUI: presenting modal view with custom transition from frame to frame?SwiftUI:呈现具有从帧到帧的自定义过渡的模态视图?
【发布时间】:2021-09-18 11:24:17
【问题描述】:

当我使用 UIViewControllerTransitioningDelegateUIViewControllerAnimatedTransitioning 呈现 ViewController 时,我正在尝试复制我在 UIKit 中所做的事情。

因此,例如,从如下所示的视图:

我想呈现一个视图(我会说一个模态视图,但我不确定这是否是在 SwiftUI 中处理它的正确方法),它从视图 A 变成这样:

所以,我需要视图 B 从匹配视图 A 的帧逐渐淡入到几乎全屏。这个想法是用户点击 A,就好像它想将它扩展到它的细节(视图 B)。

我研究了 SwiftUI 转换,如下所示:

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
            .combined(with: .opacity)
        let removal = AnyTransition.scale
            .combined(with: .opacity)
        return .asymmetric(insertion: insertion, removal: removal)
    }
}

所以,我认为我需要构建一个自定义过渡。但是,我不知道该怎么做,但我还是新手。

我将如何构建一个过渡来处理所描述的案例?能够拥有from frameto frame...?

这是在 SwiftUI 中的正确思考方式吗?

新信息:

我已经测试了matchedGeometryEffect

例子:

struct TestParentView: View {
    
    
    @State private var expand = false
    @Namespace private var shapeTransition
    
    var body: some View {

        VStack {
            if expand {
         
                // Rounded Rectangle
                Spacer()
         
                RoundedRectangle(cornerRadius: 50.0)
                    .matchedGeometryEffect(id: "circle", in: shapeTransition)
                    .frame(minWidth: 0, maxWidth: .infinity, maxHeight: 300)
                    .padding()
                    .foregroundColor(Color(.systemGreen))
                    .animation(.easeIn)
                    .onTapGesture {
                        expand.toggle()
                    }
         
            } else {
         
                // Circle
                RoundedRectangle(cornerRadius: 50.0)
                    .matchedGeometryEffect(id: "circle", in: shapeTransition)
                    .frame(width: 100, height: 100)
                    .foregroundColor(Color(.systemOrange))
                    .animation(.easeIn)
                    .onTapGesture {
                        expand.toggle()
                    }
         
                Spacer()
            }
        }
    }

}

看起来matchedGeometryEffect 可能是完成这项工作的工具。 但是,即使使用matchedGeometryEffect,我仍然无法解决这两个问题:

  1. 如何添加淡入/淡出动画?
  2. 查看matchedGeometryEffect 的行为,当我“关闭”视图 B 时,视图 B 立即消失,我们看到的动画是视图 A 从 B 回到视图 A 的原始帧。我实际上希望视图 B 在淡出时缩小到 A 所在的位置。

【问题讨论】:

    标签: swiftui transition modalviewcontroller


    【解决方案1】:

    您必须在要转换的两个视图上使用.matchedGeometryEffect 修饰符。

    这是一个例子:

    struct MatchedGeometryEffect: View {
        
        @Namespace var nspace
        @State private var toggle: Bool = false
        
        var body: some View {
            HStack {
                if toggle {
                    VStack {
                        Rectangle()
                            .foregroundColor(Color.green)
                            .matchedGeometryEffect(id: "animation", in: nspace)
                            .frame(width: 300, height: 300)
                        
                        Spacer()
                    }
                    
                }
                
                if !toggle {
                    VStack {
                        
                        Spacer()
                        
                        Rectangle()
                            .foregroundColor(Color.blue)
                            .matchedGeometryEffect(id: "animation", in: nspace)
                            .frame(width: 50, height: 50)
                    }
                }
            }
            .padding()
            .overlay(
            
                
                Button("Switch") { withAnimation(.easeIn(duration: 2)) { toggle.toggle() } }
                
            
            )
        }
    }
    

    图片应该是 GIF

    使用此修饰符的主要两部分是idnamespace

    您尝试匹配的两个视图的id 必须相同。然后它们也必须在同一个命名空间中。命名空间使用@Namespace 属性包装器在顶部声明。在我的示例中,我使用了“动画”,但它实际上可以是任何东西,最好是能够从其他类型的动画中唯一识别视图的东西。

    另一个重要的信息是控制视图显示/隐藏的“@State”变量是动画的。这是通过使用withAnimation { toggle.toggle() } 完成的。

    我对此也很陌生,因此有关更多信息,您可以阅读我从 Swift-UI 实验室找到的这篇文章:

    https://swiftui-lab.com/matchedgeometryeffect-part1/

    【讨论】:

    • 我会研究一下看看。看起来很有希望。我想我想从这种方法中唯一想知道的是删除关于关闭和淡入淡出动画的视图......
    • 找到此链接。也非常有帮助。感谢您向我指出matchedGeometryEffect。 sarunw.com/posts/a-first-look-at-matchedgeometryeffect
    • matchedGeometryEffect 可能不支持实际的模态/导航转换。不知道如何在 SwiftUI 中正确处理自定义模态表示方面的事情......
    • 感谢那篇文章,也非常有用!至于对模态/导航转换的支持,我认为不支持。这是一个好问题,我也想要这个答案哈哈
    猜你喜欢
    • 2022-07-21
    • 1970-01-01
    • 2013-04-15
    • 2021-10-07
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    相关资源
    最近更新 更多