iOS 17 SwiftUI ScrollView:实现堆叠转并排滚动动画
实现从堆叠到并排的滚动平滑过渡动画
我想要实现如下动画效果:视图初始显示时,ScrollView内的视图互相堆叠在后方;当滚动ScrollView时,视图平滑过渡为并排排列。
预期效果

初始代码
struct ContentView: View { private let colors: [Color] = [.red, .green, .blue, .yellow, .purple, .black, .brown, .cyan, .gray, .indigo, .orange, .pink, .mint, .teal] var body: some View { VStack { ScrollView(.horizontal) { LazyHStack(spacing: 10.0) { ForEach(colors, id: \.self) { color in RoundedRectangle(cornerRadius: 25.0) .foregroundStyle(color) .containerRelativeFrame(.horizontal) .scrollTransition { content, phase in content .opacity(phase.isIdentity ? 1: 0.2) .scaleEffect(y: phase.isIdentity ? 1.0 : 0.8) } } } .scrollTargetLayout() } .contentMargins(60.0, for: .scrollContent) .scrollTargetBehavior(.viewAligned) .scrollIndicators(.hidden) .frame(maxHeight: 400.0) Spacer() } } }
当前初始代码效果

目前我已实现视图并排显示的效果,但无法实现从堆叠状态到并排状态的平滑过渡。
改进后的代码(感谢Mat的帮助)
struct ColorViewModel: Identifiable { let id: Int let color: Color } struct ContentView: View { private let colors: [ColorViewModel] = [.init(id: 0, color: .red), .init(id: 1, color: .yellow), .init(id: 2, color: .green), .init(id: 03, color: .blue), .init(id: 04, color: .purple), .init(id: 05, color: .pink), .init(id: 06, color: .brown), .init(id: 07, color: .indigo), .init(id: 08, color: .black), .init(id: 09, color: .teal), .init(id: 10, color: .gray), .init(id: 011, color: .white), .init(id: 012, color: .cyan)] @State private var hasScrolled: Bool = false var body: some View { VStack { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 10.0) { ForEach(0 ..< colors.count, id: \.self) { number in RoundedRectangle(cornerRadius: 25.0) .frame(maxHeight: 300.0) .containerRelativeFrame(.horizontal) .foregroundStyle(colors[number].color) .if(!hasScrolled) { view in view .padding(.trailing, colors[number].id == colors.last?.id ? 0 : -220) .zIndex(CGFloat(-number)) } // .scrollTransition { content, phase in // content // .opacity(phase.isIdentity ? 1 : 0.2) // .scaleEffect(y: phase.isIdentity ? 1.0 : 0.8) // } } } .scrollTargetLayout() } .contentMargins(60.0, for: .scrollContent) .scrollTargetBehavior(.viewAligned) Spacer() } } } extension View { @ViewBuilder func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View { if condition { transform(self) } else { self } } }
当前改进后效果

现在需要整合两种状态,实现从堆叠到并排的平滑滚动动画,寻求帮助。
内容的提问来源于stack exchange,提问作者bubu
相关产品推荐
相关产品推荐

