SwiftUI - 如何为数组元素对应的组件设置动画?
SwiftUI - How to animate components corresponding to array elements?
我在SwiftUI中有一个圆的HStack,圆的个数是根据数组的长度来决定的,像这样:
@State var myArr = [...]
...
ScrollView(.horizontal) {
HStack {
ForEach(myArr) { item in
Circle()
//.frame(...)
//.animation(...) I tried this, it didn't work
}
}
}
然后我有一个按钮可以将一个元素附加到这个数组,有效地向视图添加一个圆圈:
Button {
myArr.append(...)
} label: {
...
}
该按钮按预期工作,但是,添加到视图中的新圆圈出现得非常突然,而且看起来很不稳定。我怎样才能以任何方式制作动画?也许它从侧面滑入,或者从一个很小的圆圈长到正常大小。
您缺少转换,这是您要查找的内容:
struct ContentView: View {
@State private var array: [Int] = Array(0...2)
var body: some View {
ScrollView(.horizontal) {
HStack {
ForEach(array, id:\.self) { item in
Circle()
.frame(width: 50, height: 50)
.transition(AnyTransition.scale)
}
}
}
.animation(.default, value: array.count)
Button("add new circle") {
array.append(array.count)
}
Button("remove a circle") {
if array.count > 0 {
array.remove(at: array.count - 1)
}
}
}
}
自动滚动到最后一个圆圈的版本:
struct myItem: Identifiable, Equatable {
let id = UUID()
var size: CGFloat
}
struct ContentView: View {
@State private var myArr: [myItem] = [
myItem(size: 10),
myItem(size: 40),
myItem(size: 30)
]
var body: some View {
ScrollViewReader { scrollProxy in
VStack(alignment: .leading) {
Spacer()
ScrollView(.horizontal) {
HStack {
ForEach(myArr) { item in
Circle()
.id(item.id)
.frame(width: item.size, height: item.size)
.transition(.scale)
}
}
}
.animation(.easeInOut(duration: 1), value: myArr)
Spacer()
Button("Add One") {
let new = myItem(size: CGFloat.random(in: 10...100))
myArr.append(new)
}
.onChange(of: myArr) { _ in
withAnimation {
scrollProxy.scrollTo(myArr.last!.id, anchor: .trailing)
}
}
.frame(maxWidth: .infinity, alignment: .center)
}
.padding()
}
}
}
我在SwiftUI中有一个圆的HStack,圆的个数是根据数组的长度来决定的,像这样:
@State var myArr = [...]
...
ScrollView(.horizontal) {
HStack {
ForEach(myArr) { item in
Circle()
//.frame(...)
//.animation(...) I tried this, it didn't work
}
}
}
然后我有一个按钮可以将一个元素附加到这个数组,有效地向视图添加一个圆圈:
Button {
myArr.append(...)
} label: {
...
}
该按钮按预期工作,但是,添加到视图中的新圆圈出现得非常突然,而且看起来很不稳定。我怎样才能以任何方式制作动画?也许它从侧面滑入,或者从一个很小的圆圈长到正常大小。
您缺少转换,这是您要查找的内容:
struct ContentView: View {
@State private var array: [Int] = Array(0...2)
var body: some View {
ScrollView(.horizontal) {
HStack {
ForEach(array, id:\.self) { item in
Circle()
.frame(width: 50, height: 50)
.transition(AnyTransition.scale)
}
}
}
.animation(.default, value: array.count)
Button("add new circle") {
array.append(array.count)
}
Button("remove a circle") {
if array.count > 0 {
array.remove(at: array.count - 1)
}
}
}
}
自动滚动到最后一个圆圈的版本:
struct myItem: Identifiable, Equatable {
let id = UUID()
var size: CGFloat
}
struct ContentView: View {
@State private var myArr: [myItem] = [
myItem(size: 10),
myItem(size: 40),
myItem(size: 30)
]
var body: some View {
ScrollViewReader { scrollProxy in
VStack(alignment: .leading) {
Spacer()
ScrollView(.horizontal) {
HStack {
ForEach(myArr) { item in
Circle()
.id(item.id)
.frame(width: item.size, height: item.size)
.transition(.scale)
}
}
}
.animation(.easeInOut(duration: 1), value: myArr)
Spacer()
Button("Add One") {
let new = myItem(size: CGFloat.random(in: 10...100))
myArr.append(new)
}
.onChange(of: myArr) { _ in
withAnimation {
scrollProxy.scrollTo(myArr.last!.id, anchor: .trailing)
}
}
.frame(maxWidth: .infinity, alignment: .center)
}
.padding()
}
}
}