ForEach(0..<3, id: .self) { number in {
Button(action: {
self.flagTapped(number: index)
withAnimation(Animation.interpolatingSpring(stiffness: 15.0, damping: 3.0)) {
animationAmount2 += 360
}
}) {
Image(self.countries[index])
.renderingMode(.original)
}
.clipShape(Capsule())
.overlay(Capsule().stroke(Color.black, lineWidth: 1)
.shadow(color: .black, radius: 10, x: 3, y: 3)
.rotation3DEffect(
.degrees(animationAmount2),
axis: (x: 0.0, y: 1.0, z: 0.0),
anchor: .center,
anchorZ: 0.0,
perspective: 1.0
)
}
它是有效的,但问题是,当你按下任何按钮时,每个按钮都会动画化,因为animationAmount2是@State属性,所以当它更新时,每个按键都会动画,而不仅仅是按下的那个。
我的下一个想法是创建一个自定义按钮,并在其中插入动画代码和属性,这样按钮就可以单独设置动画。结果是:
func getFlagView(index: Int) -> some View {
let flag = CustomButton(country: countries[index], index: index) { (Index) in
flagTapped(number: index)
}
return flag
}
我现在在ForEach中调用这个函数,它完美地插入了按钮,只有我按下的按钮会旋转。问题是,当视图刷新时,它永远不会重新绘制按钮。ForEach正在执行,但它只是忽略了对getFlagView的调用。
在CustomButton调用的末尾添加.id(UUID(((修复了以下问题:
func getFlagView(index: Int) -> some View {
let flag = CustomButton(country: countries[index], index: index) { (Index) in
flagTapped(number: index)
}.id(UUID())
return flag
}
现在,当视图按预期刷新时,按钮会重新绘制,但动画不起作用。我真的不知道为什么添加UUID会破坏动画。
为了让SwiftUI为按钮设置动画,它需要能够观察到唯一标识视图的渲染之间的变化。在第一种情况下,您的视图具有id的0
、1
和2
。所以动画成功了。
当您应用.id(UUID())
时,这会在每次绘制按钮时为其提供一个唯一的id
。因此,SwiftUI不会看到您更改了一个按钮,因为每次执行ForEach
时,它总是将这3个按钮视为3个全新的按钮。
您需要的是一个id
,它可以唯一地识别每个按钮,但在国家/地区发生变化之前,它不会发生变化。您需要一个唯一标识每个国家的id
,并且id
是国家的名称。
更改您的getFlagView
以使用国家名称作为id
:
func getFlagView(index: Int) -> some View {
let flag = CustomButton(country: countries[index], index: index) { (Index) in
flagTapped(number: index)
}.id(countries[index])
return flag
}