SwiftUI Вложенные переходы и анимация
У меня горизонтальный ScrollView
что содержит некоторые Rectangle
с. Я пытаюсь добиться исчезновения каждогоRectangle
а затем скрыть (удалить) ScrollView
.
Я частично добился этого:
Я сказал частично, потому что, как видите, Rectangle
s удалены, но 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 ответ
Мое решение вашей проблемы - создать новый state
только для прокрутки, затем оберните прямоугольники в группу и оберните группу в if show
и дальше onDisappear
установлен self.showScroll = false
Наконец, убедитесь, что при нажатии Tap Me!
устанавливать showScroll
к true
Это самый элегантный способ? нет, но он выполняет свою работу! https://i.stack.imgur.com/1G3i8.gif
//
// 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()
}
}