课程链接:https://www.bilibili.com/video/BV1q64y1d7x5?p=7
课程项目仓库:https://github.com/cnatom/MemorizeSwiftUI
自定义ViewModifier
使用自定义ViewModifier
,可以简化代码的编写
举个例子,下方代码中,我们给Text组件添加了两个ViewModifier
,让其拥有蓝色的字体和边框。
但是随着样式的增加,Text
后面的ViewModifier
会越来越多,显得非常难看,且复用性很差。
struct ContentView: View {
var body: some View {
VStack {
Text("Hello")
.border(.blue) // 蓝色边框
.foregroundColor(.blue) // 蓝色字体
}
}
}
通过自定义ViewModifier
,可以简化上述代码。
- 首先自定义一个
ViewModifier
。
此处的content,就是调用方的View。
struct BlueModifier: ViewModifier {
func body(content: Content) -> some View {
content // 调用方的View
.border(.blue) // 蓝色边框
.foregroundColor(.blue) // 蓝色字体
}
}
- 为
View
添加扩展
View的modifier方法可以为View添加ViewModifier
extension View{
func blueModifier()->some View{
return self.modifier(BlueModifier())
}
}
- 然后就可以愉快的使用了
struct ContentView: View {
var body: some View {
VStack {
Text("Hello")
.blueModifier() // 使用自定义的ViewModifier
}
}
}
动画Animation
添加动画的条件
- ViewModifier arguments(修饰器参数更改)
- Shapes(View形状改变)
- The existence" (or not) of a View in the UI(View在界面中存在)
只有加入UI的ViewModifier
的参数更新时,View
才会动画化。
并非所有ViewModifier
参数都是可动画的(例如,Font不是),但大多数是可动画的。
添加动画的方法
隐式(自动)方法:.animation(Animation)
如下代码所示,通过添加.animation(.easeInOut, value: show)
修饰符,使得变量show
的每次更改都会触发easeInOut
的动画样式。
最终呈现的效果是,每次点击😀,其透明度都会以动画的形式在1.0到0.5之间变化。
struct ContentView: View {
@State var show = false
var body: some View {
VStack {
Text("😀")
.opacity(show ? 1.0 : 0.5)
.animation(.easeInOut, value: show) // 添加动画
.onTapGesture {
show = !show;
}
}
}
}
需要注意的是,.animation(.easeInOut, value: show)
只能作用于其内层的ViewModifier
。
因此,如果将.opacity()
与.animation()
的颠倒顺序,如下代码所示,则不会有动画效果。
struct ContentView: View {
@State var show = false
var body: some View {
VStack {
Text("😀")
.animation(.easeInOut, value: show) // 只能修饰上方的ViewModifier
.opacity(show ? 1.0 : 0.5) // 并没有动画效果
.onTapGesture {
show = !show;
}
}
}
}
显式方法:withAnimation(Animation){ }
通过结构体Animation
,可以自定义各种动画效果。
自定义动画的各种参数,如duration
、delay
、repeat
……
还可以自定义动画曲线,如linear
、easeInOut
、spring
……
样例如下:
struct ContentView: View {
@State var show = false
var body: some View {
VStack {
Text("😀")
.opacity(show ? 1.0 : 0.5)
.onTapGesture {
// 动画效果
withAnimation (.easeInOut(duration: 0.5)){
show = !show;
}
}
}
}
}
显式动画不会覆盖隐式动画。
使用transitions为View创建进入/消失动画
struct ContentView: View {
@State var show = false
var body: some View {
VStack {
Spacer()
if(show){
// 消失/出现 动画
Text("😀😀😀😀")
.transition(AnyTransition.scale.animation(.easeInOut))
}
Spacer()
Button("点击"){
self.show.toggle()
}
}
}
}