如何插入带有交错缩放动画的一行按钮?

时间:2020-07-29 20:42:09

标签: swiftui

我正在尝试从Castro应用重新创建以下动画...

Castro Animation

(GIF速度变慢,因此您可以看到效果)

如您在上面的GIF中所看到的,当单元格被点击时,您会看到一排按钮。每个按钮都有放大和缩小效果。动画交错排列,以使第一个按钮首先完成,最后一个按钮最后完成。

我尝试过的...

struct SwiftUIView: View {
    @State var show: Bool = false
    var body: some View {
        VStack {
            Button(action: {
                withAnimation {
                    show.toggle()
                }
            }, label: {
                Text("Button")
            })
            HStack {
                if show {
                    Button(action: {}, label: { Image(systemName: "circle") })
                        .transition(.scale)
                    Button(action: {}, label: { Image(systemName: "circle") })
                        .transition(.scale)
                    Button(action: {}, label: { Image(systemName: "circle") })
                        .transition(.scale)
                }
            }

        }
    }
}

Attempt 1

如上图所示,每个按钮均会放大,但仅当视图被移除时。而且,我不知道如何错开动画。

1 个答案:

答案 0 :(得分:0)

尝试以下操作:

struct ContentView: View {
    @State var show = false
    @State var showArray = Array(repeating: false, count: 3)

    var body: some View {
        VStack {
            Button(action: toggleButtons) {
                Text("Button")
            }
            HStack {
                ForEach(showArray.indices, id: \.self) { index in
                    self.circleView(for: index)
                }
            }
        }
    }

    @ViewBuilder
    func circleView(for index: Int) -> some View {
        if show {
            ZStack {
                Image(systemName: "circle")
                    .opacity(.leastNonzeroMagnitude)
                    .animation(nil)
                if showArray[index] {
                    Image(systemName: "circle")
                        .transition(.scale)
                }
            }
        }
    }

    func toggleButtons() {
        showArray.indices.forEach { index in
            withAnimation {
                self.show = true
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(index)) {
                withAnimation {
                    self.showArray[index].toggle()
                    if index == self.showArray.count - 1, self.showArray[index] == false {
                        self.show = false
                    }
                }
            }
        }
    }
}

它使用了一些 hack 来正确对齐视图-在ZStack中有一个 fake Image,几乎没有遮盖物。