SwiftUI中的动画.animation和withAnimation

动画是通过改变视图的状态来给视图添加平滑视图变化的能力。SwiftUI中有两种类型的动画:隐式动画显式动画
不管是哪种动画,我们都需要一个被@State包装的状态属性值,通过这个值的改变来促使与之相关的UI刷新,继而执行动画。

隐式动画.animation(_:value:)

这是一个SwiftUI视图的修饰器。第一个参数的值是动画行为,它包lineareaseOuteaseIneaseInOut等。第二个参数接受一个不断变化的值,即下面用到的isAnimated.animation会对这个值做出反应。

@State var isAnimated: Bool = false
var body: some View {
    VStack {
      RoundedRectangle(cornerRadius: isAnimated ? 50 : 25)
        .fill(isAnimated ? Color.red : Color.green)
        .frame(
          width: isAnimated ? 100 : 300,
          height: isAnimated ? 100 : 300)
        .rotationEffect(Angle(degrees: isAnimated ? 360 : 0))
        .offset(y: isAnimated ? -200 : 0)
        .animation(
          Animation
          .linear(duration: 1)
          .repeatForever(autoreverses: false),
          value: isAnimated)
        .onTapGesture {
          isAnimated.toggle()
        }
    }
  }

上面代码中对RoundedRectangle设置了动画,我们通过onTapGesture手势触发动画,当点击后isAnimated的值改变,RoundedRectangle中与isAnimated有关的UI进行刷新,因为RoundedRectangle.animation动画修饰器修饰了,并且该修饰器关注isAnimated的变化,因此与isAnimated有关的UI将会以指定动画的方式刷新,效果如下面两个图。

autoreverses: false
动画1

autoreverses: true
动画2

duration

为了更精确地控制我们的动画,我们可以添加单次动画的持续时间。

// 动画执行时间为2秒
.animation(.easeInOut(duration: 2), value: value)
.repeatCount/.repeatForever

我们可以通过设置repeatCount(count) 或者 repeatForever()来设置动画重复次数等等。

// 动画执行两次
.animation(.easeInOut(duration: 1).repeatCount(2), value: value)
// 动画一直重复执行
.animation(.easeInOut(duration: 1).repeatForever(), value: value)

在设置动画重复执行是可以额外设置一个参数autoreverses,指示动画序列在向前播放后是否反向播放。
比如一个旋转动画,从0度到360度,一直循环执行:

  • 如果autoreversesfalse,当动画执行旋转到360度后,瞬间重置到0度,然后再从0度到360度做动画,这样反复执行,效果如上面动画1.
  • 如果autoreversestrue,当动画执行旋转到360度后,再从360度做动画回到0度,然后再从0度动画到360,这样反复执行,效果如上面动画2.

显示动画withAnimation()

显式动画不是视图修饰器。而是调用withAnimation()函数,并在括号之间添加想要动画化的内容。
在下面的代码中,我们在onTapGesture的执行代码快中调用withAnimation()函数,并设置动画参数,在withAnimation的闭包体里改变isAnimated的状态值,继而促使UI刷新,执行动画。

@State var isAnimated: Bool = false
var body: some View {
    VStack {
      RoundedRectangle(cornerRadius: isAnimated ? 50 : 25)
        .fill(isAnimated ? Color.red : Color.green)
        .frame(
          width: isAnimated ? 100 : 300,
          height: isAnimated ? 100 : 300)
        .rotationEffect(Angle(degrees: isAnimated ? 360 : 0))
        .offset(y: isAnimated ? -200 : 0)
        .onTapGesture {
          withAnimation(Animation
            .linear(duration: 1)
            .repeatForever(autoreverses: true)) {
              isAnimated.toggle()
            }
        }
    }
  }

我们将isAnimated的改变放到了withAnimation函数的闭包里,意味着因isAnimated的改变引起的UI变化都要以指定的动画方式执行。该段代码的执行效果如同上面的两个动画图。

内置动画类型

在SwiftUI中,系统提供了多种内置的动画类型,可以通过.animation()修饰器或者withAnimation()来应用这些动画效果。以下是一些常见的系统动画类型:

  1. linear:线性动画,以恒定速度进行动画过渡。
  2. easeIn:缓慢开始的动画,逐渐加速。
  3. easeOut:缓慢结束的动画,逐渐减速。
  4. easeInOut:缓慢开始和结束的动画,先加速后减速。
  5. easeInOut(duration: Double):缓慢开始和结束的动画,可以指定持续时间。
  6. spring:弹簧动画,具有弹性效果。
  7. interactiveSpring(response: Double, dampingFraction: Double, blendDuration: Double):交互式弹簧动画,可以调整响应、阻尼和混合持续时间。
  8. default:默认动画,系统根据情况选择合适的动画类型。
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值