如何创建类似抽屉的动画(滑出)?

时间:2020-07-24 04:25:21

标签: swiftui

想象一下,您有一张带抽屉的桌子。在关闭状态下,您只能看到桌子,因为抽屉在桌子下面。在打开状态下,您会看到位于桌子下方的抽屉(因为它向下滑动)。我该如何设置动画,以使抽屉从SwiftUI的桌子下方滑出?

此视图将在列表视图内工作,因此行的尺寸必须适应任何更改。因此,我不知道基于偏移的动画是否可以在这里工作(如in this question所示)。顶视图(书桌)和底视图(抽屉)是相同的大小。

这就是我尝试过的...

在下面的代码中,我使用矩形,但最终我将使用视图。

匹配的几何效果

struct ContentView: View {
    @Namespace private var animation
    @State var shown: Bool = false
    var body: some View {
        Group {
            if !shown {
                ZStack {
                    Rectangle().frame(width: 300, height: 80, alignment: .center)
                        .foregroundColor(.blue)
                        .matchedGeometryEffect(id: "Bottom", in: animation)
                    Rectangle().frame(width: 300, height: 80, alignment: .center)
                        .matchedGeometryEffect(id: "Top", in: animation)
                }
            } else {
                VStack(spacing: 0) {
                    Rectangle().frame(width: 300, height: 80, alignment: .center)
                        .matchedGeometryEffect(id: "Top", in: animation)
                    Rectangle().frame(width: 300, height: 80, alignment: .center)
                        .foregroundColor(.blue)
                        .matchedGeometryEffect(id: "Bottom", in: animation)
                }
            }
        }.onTapGesture {
            withAnimation(.linear(duration: 1)) {
                shown.toggle()
            }
        }
    }
}

产生这个...

matched geometry

转换

struct ContentView: View {
    @State var shown: Bool = false
    var body: some View {
        VStack(spacing: 0) {
            Rectangle().frame(width: 300, height: 80, alignment: .center)
                .zIndex(0)
            if shown {
                Rectangle().frame(width: 300, height: 80, alignment: .center)
                    .foregroundColor(.blue)
                    .zIndex(-1)
                    .transition(.move(edge: .top))
            }
        }.onTapGesture {
            withAnimation(.linear(duration: 1)) {
                shown.toggle()
            }
        }
    }
}

transition

1 个答案:

答案 0 :(得分:0)

如果抽屉(height)的大小是一个已知常数,我会这样:

var body: some View {
    ZStack {
        Rectangle()
            .foregroundColor(.blue)
            .frame(width: 300, height: 80, alignment: .center)
            .offset(y: shown ? 80 : 0)
            .animation(.easeInOut(duration: 0.2))
        
        Rectangle()
            .frame(width: 300, height: 80, alignment: .center)
    }
    .onTapGesture {
        shown.toggle()
    }
}