SwiftUI Вложенные переходы и анимации - PullRequest
0 голосов
/ 20 марта 2020

У меня есть горизонтальная 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))
    }
}

1 Ответ

0 голосов
/ 21 марта 2020

Мое решение вашей проблемы - создать новый state для одного вида прокрутки, затем обернуть прямоугольники в группе и обернуть группу в if show и onDisappear set self.showScroll = false

Наконец, убедитесь, что при нажатии Tap Me! для установки showScroll на true

Это самый элегантный способ? нет, но это делает работу! enter image description here

//
//  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()
    }
}


...