SwiftUI嵌套的过渡和动画

问题描述 投票:0回答:1

我有一个水平的ScrollView,可容纳一些Rectangle。我想要实现的是淡出每个Rectangle,然后隐藏(删除)ScrollView

我已经部分实现了这一目标:

enter image description here

我之所以说是部分原因是,如您所见,Rectangle被删除了,但是ScrollView仍然存在(请参阅属于ScrollView的蓝色边框框,我添加了一些填充以使它更可见)。

我认为我可能需要嵌套转换(每个Rectangle都有一个.move(edge:)转换,并且ScrollView应该有另一个“外部”转换-但这也可能是错误的方法。

关于如何实现此动画以及在动画结束时转换(删除)ScrollView的任何想法?我尝试了其他选择,但失败了。注意:黑色Rectangle是固定的。

这是示例代码:

struct TestAnimation: View {
    @State var show : Bool = true
    var colors : [Color] = [.red, .orange, .yellow, .green, .blue]

    var body: some View {
        VStack(alignment: .leading) {
            Spacer()

            Color.purple
                .frame(height: 100)
                .overlay(
                    Text("Tap Me!").foregroundColor(.white))
                .onTapGesture {
                    self.show.toggle()
            }

            HStack(alignment: .bottom) {
                Rectangle()
                    .fill(Color.black)
                    .frame(width: 70, height: 100)
                    .overlay(Text("A").foregroundColor(.white).font(.largeTitle))
                    .padding(8)

                    ScrollView(.horizontal, showsIndicators: false) {

                        HStack(alignment: .bottom) {
                            if show {
                                self.cellForItemAt(idx: 2)
                                self.cellForItemAt(idx: 3)
                                self.cellForItemAt(idx: 4)
                                self.cellForItemAt(idx: 5)
                            }
                        }
                        .frame(height: 100)
                        .padding(4)
                        .border(Color.red)//HStack


                    }//Scrollview
                    .padding(4)
                    .border(Color.blue)

            }
            .padding(4)
            .border(Color.gray)//Hstack
        }
    }

    func cellForItemAt(idx: Int) -> some View {
        return Rectangle()
            .fill(colors[idx-1])
            .frame(width: 70, height: 100)
            .transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(self.ripple(idx: idx)))
            .animation(ripple(idx: idx))
    }

    func ripple(idx: Int) -> Animation {
        Animation
            .easeInOut(duration: 0.8)
            .delay(0.20 * Double(colors.count - idx) : Double(idx))
    }
}
swiftui transition swiftui-animation
1个回答
0
投票

我对您的问题的解决方案是为滚动视图单独创建一个新的state,然后将矩形包装在一个组中,然后将该组包装在if show中,并在onDisappear上设置为self.showScroll = false

最后,请确保在点击Tap Me!时将showScroll设置为true

这是最优雅的方式吗?不,但是可以完成工作!

//
//  TestAnimation.swift
//  playground
//
//  Created by Muhand Jumah on 3/20/20.
//  Copyright © 2020 Muhand Jumah. All rights reserved.
//

import SwiftUI

struct TestAnimation: View {
    @State var show : Bool = true
    @State var showScroll: Bool = true
    var colors : [Color] = [.red, .orange, .yellow, .green, .blue]

    var body: some View {
        VStack(alignment: .leading) {
            Spacer()

            Color.purple
                .frame(height: 100)
                .overlay(
                    Text("Tap Me!").foregroundColor(.white))
                .onTapGesture {
                    self.showScroll = true
                    self.show.toggle()
            }

            HStack(alignment: .bottom) {
                Rectangle()
                    .fill(Color.black)
                    .frame(width: 70, height: 100)
                    .overlay(Text("A").foregroundColor(.white).font(.largeTitle))
                    .padding(8)

                if(showScroll) {
                    ScrollView(.horizontal, showsIndicators: false) {

                        HStack(alignment: .bottom) {
                            if show {
                                Group {
                                    self.cellForItemAt(idx: 2)
                                    self.cellForItemAt(idx: 3)
                                    self.cellForItemAt(idx: 4)
                                    self.cellForItemAt(idx: 5)
                                }.onDisappear {
                                    self.showScroll = false
                                }
                            }
                        }
                        .frame(height: 100)
                        .padding(4)
                        .border(Color.red)//HStack


                    }//Scrollview
                    .padding(4)
                    .border(Color.blue)
                }

            }
            .padding(4)
            .border(Color.gray)//Hstack
        }
    }

    func cellForItemAt(idx: Int) -> some View {
        return Rectangle()
            .fill(colors[idx-1])
            .frame(width: 70, height: 100)
            .transition(AnyTransition.move(edge: .bottom).combined(with: .opacity).animation(self.ripple(idx: idx)))
            .animation(ripple(idx: idx))
    }

    func ripple(idx: Int) -> Animation {
        Animation
            .easeInOut(duration: 0.8)
            .delay(0.20 * Double(colors.count - idx))
    }
}

struct TestAnimation_Previews: PreviewProvider {
    static var previews: some View {
        TestAnimation()
    }
}


祝你好运

© www.soinside.com 2019 - 2024. All rights reserved.