我有一个有条件地显示按钮的组件视图。我希望这个按钮在出现/消失时有动画效果。
.transition(.move(edge: .trailing))
做我想做的事。
但是,如果组件的父组件移动,子组件的动画将相对于全局帧运行,而不是相对于其父组件的帧运行。
我相信应该有一种方法来改变这种行为。组件的实现不应该取决于它的使用方式。
我有另一种方法来实现我想要的,但它不是过渡动画。它手动修改偏移量。但是,我相信应该有一个使用转换的解决方案。组件的子组件可能需要出现/消失生命周期用于其他目的。
import SwiftUI
import PlaygroundSupport
struct Component: View {
let state: Bool
var body: some View {
HStack() {
Text("Placeholder")
.padding()
Spacer()
if (state) {
Color.red
.frame(width: 20, height: 20)
.padding()
.transition(.move(edge: .trailing))
}
}
.frame(width: 200, height: 200)
.background(Color.blue)
.clipped()
}
}
struct ComponentAlternative: View {
let state: Bool
var body: some View {
HStack() {
Text("Placeholder")
.padding()
Spacer()
Color.red
.frame(width: 20, height: 20)
.padding()
.transition(.move(edge: .trailing))
.offset(x: state ? 0 : 50)
}
.frame(width: 200, height: 200)
.background(Color.blue)
.clipped()
}
}
struct DemoView: View {
@State private var state: Bool = false
var body: some View {
ZStack {
Toggle(isOn: $state, label: {})
Component(state: state)
.frame(width: 200, height: 200)
.background(Color.blue)
.clipped()
.padding(.top, state ? 200 : 0)
}
.frame(width: 400, height: 400)
.animation(.default.speed(0.1), value: state)
}
}
PlaygroundPage.current.setLiveView(DemoView())
geometryGroup
的用途。将其添加到 ComponentView
,但在 .padding(.top, state ? 200 : 0)
之前。
Component(state: state)
.geometryGroup() // <-----
.frame(width: 200, height: 200)
.background(Color.blue)
.clipped()
.padding(.top, state ? 200 : 0)
这基本上可以防止填充动画直接影响
Component
。父级为其填充设置动画,而 Color.red
则为过渡设置动画,所有这些都是单独进行的。