#swiftui
#swiftui
Вопрос:
Я пытаюсь добиться следующей анимации: когда я нажимаю на прямоугольник, прямоугольник должен быть расширен на всю ширину с помощью кнопки закрытия в углу, а под этим прямоугольником должен появиться ScrollView. Пока это работает без каких-либо проблем. Теперь я хотел бы отобразить ScrollView немного позже, чем расширенный прямоугольник. Итак, когда я нажимаю на прямоугольник: сначала должен появиться расширенный прямоугольник с кнопкой закрытия, а через 3 секунды — ScrollView.
struct Playground: View {
@Namespace var namespace
@State var show = false
private let gridItems = [GridItem(.flexible())]
var body: some View {
if show {
VStack{
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)){
Rectangle()
.matchedGeometryEffect(id: "A", in: namespace, isSource: show)
.frame(height: 300)
.frame(maxWidth: .infinity)
Image(systemName: "xmark")
.font(.system(size: 25))
.foregroundColor(.white)
.background(Color.red)
.padding(20)
.onTapGesture {
withAnimation(.spring()){
self.show = false
}
}
}
// SHOW THIS SCROLLVIEW 3 SECONDS LATER
ScrollView{
LazyVGrid(columns: gridItems){
ForEach(0..<10){ cell in
Text("(cell)")
}
}
}
.animation(Animation.spring().delay(3)) // doesn't work!
}
} else {
Rectangle()
.matchedGeometryEffect(id: "A", in: namespace, isSource: !show)
.frame(width: 100, height: 100)
.onTapGesture {
withAnimation(.spring()){
self.show = true
}
}
}
}
}
Ответ №1:
Нам нужно сделать разделенную анимацию (и связанное состояние) для ScrollView
в этом сценарии.
Вот возможный подход. Протестировано с Xcode 12.1 / iOS 14.1
struct Playground: View {
@Namespace var namespace
@State var show = false
private let gridItems = [GridItem(.flexible())]
@State private var showItems = false
var body: some View {
if show {
VStack{
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)){
Rectangle()
.matchedGeometryEffect(id: "A", in: namespace, isSource: show)
.frame(height: 300)
.frame(maxWidth: .infinity)
Image(systemName: "xmark")
.font(.system(size: 25))
.foregroundColor(.white)
.background(Color.red)
.padding(20)
.onTapGesture {
withAnimation(.spring()){
self.show = false
}
}
}
VStack {
if showItems {
ScrollView{
LazyVGrid(columns: gridItems){
ForEach(0..<10){ cell in
Text("(cell)")
}
}
}
} else {
Spacer()
}
}
.onAppear { showItems = true }
.onDisappear { showItems = false }
.animation(Animation.spring().delay(3), value: showItems)
}
} else {
Rectangle()
.matchedGeometryEffect(id: "A", in: namespace, isSource: !show)
.frame(width: 100, height: 100)
.onTapGesture {
withAnimation(.spring()){
self.show = true
}
}
}
}
}