当在两个状态之间动画视图时,如何实现不仅从state1到state2或返回的动画,而且设置特定的动画分数,就像在UIKit中使用UIViewPropertyAnimator的fractionComplete一样?
这里是代码,我可以动画之间的2个国家的水龙头。但是我需要follow slider value(或者从socket获取value,或者scrollView offset,无论CGFloat从0到1是什么)。基本上,需要传递一个动画片段,以便视图在时间轴上静态地表示它的状态。简而言之,需要设置动画进度。
struct TransitionView: View {
@Namespace var namespace
@State var isExpanded: Bool = false
@ViewBuilder
var body: some View {
VStack {
switch isExpanded {
case true:
VStack {
Circle()
.strokeBorder(Color.green, lineWidth: 5)
.matchedGeometryEffect(id: "circle", in: namespace)
.frame(width: 70, height: 70)
Text(verbatim: "I am Circle")
.matchedGeometryEffect(id: "text", in: namespace)
}
case false:
HStack {
Circle()
.strokeBorder(Color.red, lineWidth: 5)
.matchedGeometryEffect(id: "circle", in: namespace)
.frame(width: 30, height: 30)
Text(verbatim: "I am Circle")
.matchedGeometryEffect(id: "text", in: namespace)
}
}
}
.contentShape(Rectangle())
.animation(.easeInOut, value: isExpanded)
.onTapGesture {
isExpanded.toggle()
}
}
}
字符串
的数据
1条答案
按热度按时间qyzbxkaa1#
您在示例中看到的实际上是从水平布局的circle+label到垂直布局的circle+label的过渡。但是这两组视图是相互独立的,因此对颜色等属性的更改不会被动画化。
使用
matchedGeometryEffect
有助于从一个布局到另一个布局的平滑过渡,但这更多的是由于运气。这是因为你没有找到来源。根据documentation,如果“isSource = true的组中当前插入的视图的数量不正好是一个”,则结果未定义。换句话说,您没有正确使用matchedGeometryEffect
。为了更好地控制动画,我建议进行以下更改:
1.将两个布局合并为一个
更改视图结构,以便只有一个圆和一个标签。这很棘手,因为您要将布局从水平更改为垂直,但一种方法是将圆应用为具有计算偏移的叠加:
字符串
2.将boolean替换为合适的变量
如果你希望转换能够表示一个中间状态,那么你需要用一个可以用来保存这个状态的变量来替换布尔值,比如CGFloat。如果我们坚持在进度达到一半时进行简单的颜色更改,则可以如下实现:
型
3.复杂动画使用
Animatable
视图修饰符动画通过确定开始位置和结束位置并在它们之间进行插值来工作。当更改是线性的时,这很有效,就像这里的圆大小和偏移一样。但是,如果中间状态涉及到更复杂的函数,例如遵循非线性路径,则可能需要实现自己的
Animatable
视图修饰符。我不认为这适用于这里,因为你更感兴趣的是表现一个冻结的中间状态,而不是执行一个不规则的动画。但有关可设置动画的视图修改器的更多信息,请参见以下其他答案:
Change Reverse Animation Speed SwiftUI的
swiftui Alignment Guide for two view