SwiftUI 动画:一些隐式过渡动画在 iOS 13 上被破坏了?
Posted
技术标签:
【中文标题】SwiftUI 动画:一些隐式过渡动画在 iOS 13 上被破坏了?【英文标题】:SwiftUI animation: Some implicit transition animations broken on iOS 13? 【发布时间】:2020-03-31 20:45:13 【问题描述】:在 Xcode 11.3.1 和 11.4 上测试:
将隐式动画附加到过渡时,某些过渡类型似乎被破坏了。具体来说,任何与位置相关的转换都不会应用给定的隐式动画。 .slide
、.move
、.offset
坏了。 .opacity
和 .scale
似乎还可以。 (见附件)
显式动画似乎在所有情况下都可以正常工作。
即使使用自定义复合过渡,与位置相关的子过渡也不响应隐式动画。
这是错误还是预期行为?
如果您想基于隐式属性更改为特定 UI 元素触发多个不同的动画曲线,这似乎是个问题。
struct MyExample: View
@State private var isShowing = true
private let myAnimation = Animation.spring(response: 0.8, dampingFraction: 0.2, blendDuration: 3.0)
var body: some View
VStack(spacing:20)
if self.isShowing
Text("Opacity").modifier(MyBigFont())
.transition(AnyTransition.opacity.animation(myAnimation))
Text("Scale").modifier(MyBigFont())
.transition(AnyTransition.scale.animation(myAnimation))
Text("Slide").modifier(MyBigFont())
.transition(AnyTransition.slide.animation(myAnimation))
Text("Move").modifier(MyBigFont())
.transition(AnyTransition.move(edge: .trailing).animation(myAnimation))
Text("Offset").modifier(MyBigFont())
.transition(AnyTransition.offset(x: 20, y: 0).animation(myAnimation))
Text("Custom").modifier(MyBigFont())
.transition(AnyTransition.myCustomTransition.animation(myAnimation))
Spacer()
Button(action:
self.isShowing.toggle()
)
Text("Implicit Toggle")
Button(action:
withAnimation(self.myAnimation)
self.isShowing.toggle()
)
Text("Explicit Toggle")
struct MyBigFont: ViewModifier
func body(content: Content) -> some View
content
.lineLimit(1)
.padding()
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(8)
.font(Font.system(size: 21).bold())
struct MyCustomTransition: ViewModifier
var isEnabled: Bool
func body(content: Content) -> some View
if isEnabled
return content
.offset(x: 20.0, y: 0.0)
.opacity(0)
else
return content
.offset(x: 0.0, y: 0.0)
.opacity(1)
extension AnyTransition
static let myCustomTransition = AnyTransition.modifier(
active: MyCustomTransition(isEnabled: true),
identity: MyCustomTransition(isEnabled: false))
struct ContentView_Previews: PreviewProvider
static var previews: some View
VStack
MyExample()
Spacer()
【问题讨论】:
【参考方案1】:根据 Javier 的说法,从 Xcode 11.2 开始,过渡的隐式动画不再起作用
如果有人有更新的信息,请回复。
请注意,从 XCode 11.2 开始,过渡不再适用于隐式动画。
https://swiftui-lab.com/advanced-transitions/
【讨论】:
【参考方案2】:要使隐式转换正确动画化,需要制作包含这些转换的动画容器。
使用 Xcode 11.4 / ios 13.4 测试。
这是唯一的修复:
struct MyExample: View
@State private var isShowing = true
private let myAnimation = Animation.spring(response: 0.8, dampingFraction: 0.2, blendDuration: 3.0)
var body: some View
VStack(spacing:20)
if self.isShowing
... // all your code here
.animation(myAnimation) // << fix !!
【讨论】:
但这不会触发附加到每个过渡的隐式动画。它用显式动画覆盖它们。这与使用单个withAnimation
包装属性更改的效果相同【参考方案3】:
Asperi 的回答是完全正确的,刚刚用 Xcode 13.2.1 和 iOS 15.2 / macOS 12.2 测试了它,下面这个简单的例子:
struct ContentView: View
@State private var show = false
var body: some View
VStack(spacing: 20)
roundedRect(color: .blue)
if show
roundedRect(color: .red)
.transition(.opacity.animation(.easeInOut))
Spacer()
Button(show ? "Hide" : "Show")
show.toggle()
.animation(.easeInOut)
.padding()
.frame(width: 190, height: 420, alignment: .top)
令人惊讶的是,这有效:
Opacity transition with implicit animation
然后我尝试了相同的设置,只是使用 .slide
转换,然后它停止工作:
Slide transition with implicit animation
然后我尝试将动画移到下一个容器(VStack),就像上面建议的 Asperi 一样:
struct ContentView: View
@State private var show = false
var body: some View
VStack(spacing: 20)
roundedRect(color: .blue)
if show
roundedRect(color: .red)
.transition(.slide)
Spacer()
Button(show ? "Hide" : "Show")
show.toggle()
.animation(.easeInOut)
.padding()
.frame(width: 190, height: 420, alignment: .top)
瞧,转场又开始动画了。
Slide transition with implicit animation on the containing VStack
【讨论】:
是的,这是为单个视图设置动画的解决方法。但看看我对 Asperi 的回答的评论。当您有多个子视图,每个子视图都想要自己不同的隐式动画时,它并不能解决问题。 (就像我原来的例子) 不,不是。在您最初的问题中,您为每个视图(.animation(myAnimation))使用相同的动画,只是不同的过渡。因此,如果您保持 Text 上的过渡,但将 .animation(myAnimation) 移动到包含 VStack 上,它应该可以工作。 我的问题是关于每个元素触发不同的隐式过渡和动画。据我所知,没有解决方法。已接受答案中的链接似乎仍然正确(隐式转换不起作用)。 这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review以上是关于SwiftUI 动画:一些隐式过渡动画在 iOS 13 上被破坏了?的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI4.0有趣的动画升级:新iOS16视图内容过渡动画