我们知道,要想SwiftUI开发更加鲜活美味,为视图多添加点欢快的动画总是没错的。
在iOS 13至15的系统中,当SwiftUI视图的外观发生改变时,我们可以很方便的为其自动产生动画效果:
这仅需用withAnimation方法块包裹驱动动画的属性变更即可:
Text("Copyright@2022-08-08 🐼")
.font(.largeTitle)
.multilineTextAlignment(.center)
.offset(x: flag ? 50 : 0, y: flag ? 50 : 0)
.frame(height: flag ? 300 : 150)
.border(Color.red, width: 3.0)
.onTapGesture {
withAnimation(.default.speed(0.5)) {
flag.toggle()
}
}
不过,以上自动产生的动画效果仅限于视图特定属性的改变,比如尺寸或位置等。
如果视图的内容发生了变化,是不会有任何动画效果的:
Text("Copyright@2022-08-08 🐼")
.font(.largeTitle)
.fontWeight(flag ? .black : .thin)
.foregroundColor(flag ? .yellow : .red)
.multilineTextAlignment(.center)
.onTapGesture {
withAnimation(.default.speed(0.5)) {
flag.toggle()
}
}
运行如下,毫无动画的痕迹:
不过,这在iOS 16中悄然发生了变化。
在iOS 16中,我们可以为视图应用新的内容过渡动画(Content Transition),让其仅在内容发生变化时也能“明艳动人”。
下面,就让我们一起来看下吧!😉
在iOS 16中,为视图应用新的内容过渡动画很简单,只需为其添加新的 contentTransition() 修改器方法即可:
VStack {
Text("Copyright@2022-08-08 🐼")
.font(.largeTitle)
.fontWeight(flag ? .black : .thin)
.foregroundColor(flag ? .yellow : .red)
.multilineTextAlignment(.center)
.contentTransition(.interpolate)
.onTapGesture {
withAnimation(.default.speed(0.2)) {
flag.toggle()
}
}
注意,上面的代码需要在Xcode 14beta中才能编译通过。
现在,来看一下效果:
不过据我测试,在iOS 16中即使不为视图应用contentTransition()方法,也会自动产生内容过渡动画。
想在iOS 16中关闭内容动画也很简单,为contentTransition修改器传入.identity实参即可:
view
.contentTransition(.identity)
值得一提的是,对于文本的内容过渡动画,如果变化文本里包括中文等其它文字,可能不会产生你期待的效果:
如上图所示,貌似SwiftUI还不知道如何做中文文本的内容动画 😭
如果被改变的只是视图中的数字显示,那么内容动画提供一个特别的numericText动画类型,专门用于此种情况:
如上,我们在最左边的视图上应用了numericText内容动画,在中间视图上应用了interpolate内容动画,而在最右边的视图上未应用任何动画。代码如下:
@State var i = 1000
HStack(spacing: 50) {
Text(verbatim: "\(i)")
.contentTransition(.numericText())
Text(verbatim: "\(i)")
.contentTransition(.interpolate)
Text(verbatim: "\(i)")
.contentTransition(.identity)
}
.font(.largeTitle)
Button("减 1"){
withAnimation {
i -= 1
}
}
最后需要说明的是,numericText内容动画类型目前只在Xcode 14 beta4+ 版本中支持。
SwiftUI还为内容过渡动画提供环境变量的支持,这意味着我们可以根据上级视图指定动画类型做不同的操作了:
struct CustomView: View {
@Environment(\.contentTransition) var transition
var body: some View {
VStack {
switch transition {
case .interpolate:
Text("interpolate")
case .identity:
Text("identity")
case .opacity:
Text("opacity")
//case .numericText(): 此句会出错,遂改用以下一句判断
default:
Text("numericText")
}
}
}
}
CustomView()
.contentTransition(.interpolate)
在本篇博文中,我们介绍了iOS 16中新的内容过渡动画(Content Transition),使用它我们可以更富表现力的点缀SwiftUI视图了。
那么,感谢观赏,再会。😎