1

我创建了一个插入三个按钮的简单函数。我想要一个单独的按钮在按下时旋转。我最初的尝试是这样的:

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 会破坏动画。

4

1 回答 1

2

为了让 SwiftUI 为您的按钮设置动画,它需要能够观察唯一标识视图的渲染之间的变化。在您的第一种情况下,您的视图具有 id 012。所以动画成功了。

当您应用 时,这会在每次绘制.id(UUID())按钮时赋予它们唯一性。因此 SwiftUI 不会看到您更改了按钮,因为每次执行时它总是将 3 个按钮视为 3 个全新的按钮。id ForEach

您需要的是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
}
于 2020-09-22T11:45:29.483 回答