SwiftUI绑定动画作用范围及VStack内状态修改报错咨询
struct ContentView: View { @State private var animationAmount = 1.0 var body: some View { VStack { Stepper("Scale amount", value: $animationAmount.animation(.linear), in: 1...10) Spacer() Button("Tap Me") { animationAmount += 1 } .padding(50) .background(.red) .foregroundColor(.white) .clipShape(Circle()) .scaleEffect(animationAmount) } } }
问题1
我为Stepper的绑定值$animationAmount添加了.animation(.linear)修饰符,理解中该绑定的变更会被动画化。请问是否仅该绑定值的变化会触发动画?若视图中其他变更恰好发生在该绑定值变化之前,这些变更是否也会被动画化?
问题2
为何无法在VStack中放入如下修改animationAmount的if语句:
if animationAmount > 1.0 { animationAmount += 0.25 }
报错提示“()不遵循View协议”,请解释原因。
问题1解答
当你给绑定加.animation(.linear)时,只有这个绑定的变更会触发对应动画——准确说,是所有依赖这个绑定值的视图属性,会在绑定值变化时执行线性动画。
如果视图里还有其他状态变更发生在这个绑定变化之前,只要那些变更没关联到这个带动画的绑定,也没自己加动画修饰符,就不会被这个动画影响。但要注意:如果其他状态变更和这个绑定的变化在同一帧触发(比如同一个事件里改了两个状态),且那些状态对应的视图属性本身有动画,那会各自触发动画,但和这个绑定的动画是两回事。
总结就是,这个绑定的动画修饰符只管自己绑定值变化引发的视图更新,不会牵连无关的状态变更。
问题2解答
SwiftUI的body必须返回符合View协议的内容,VStack里的每一项都得是视图。你写的if语句是一段修改状态的逻辑代码,它执行完啥也不返回(返回Void,也就是()),而()不是视图,所以报错说它不遵循View协议。
要实现这种逻辑,得把代码放到合适的地方:
- 比如
onAppear、onChange这类生命周期回调里 - 或者按钮点击事件、其他触发动作中
- 也可以给
@State加didSet观察器:@State private var animationAmount = 1.0 { didSet { if animationAmount > 1.0 { animationAmount += 0.25 } } }
内容的提问来源于stack exchange,提问作者Tom Mils
相关产品推荐
相关产品推荐

