通过Jetpack Compose实现双击点赞动画效果

目录
  • 实现步骤
    • 先红色画个爱心
    • 点击事件加动画
  • 完整代码
    • 效果图

      实现步骤

      先红色画个爱心

      Icon(
          Icons.Filled.Favorite,
          "爱心",
          Modifier
              .align(Alignment.Center)    
          tint = Color.Red
      )

      点击事件加动画

      双击监听

      .pointerInput(Unit) {
          detectTapGestures(
              onDoubleTap = {
                ...
              }
          )
      }
      #### **API 介绍**
      | API名称 | 作用 |
      | --- | --- |
      | detectTapGestures | 监听点击手势 |
      
      > 与 Clickable Modifier 不同的是,detectTapGestures 可以监听更多的点击事件。作为手机监听的基础 API,必然不会存在 Clickable Modifier 所拓展的涟漪效果
      
      detectTapGestures 提供了四个可选参数
      -   onDoubleTap (可选):双击时回调
      -   onLongPress (可选):长按时回调
      -   onPress (可选):按下时回调
      -   onTap (可选):轻触时回调
      
      我们用到的就是`onDoubleTap`

      用枚举定义三个变量 开始、显示和消失

      enum class LikedStates {
          Initial,
          Liked,
          Disappeared
      }

      remember保持数据状态,mutableStateOf监听状态变化

      var transitionState by remember {
          mutableStateOf(MutableTransitionState(LikedStates.Disappeared))
      }

      MutableTransitionState包含两个字段:currentState和targetState。currentState初始化为提供的initialState,并且只能通过转换进行变异。targetState也初始化为initialState。可以对其进行变异,以改变使用updateTransition使用MutableTransitionState创建的过渡动画的过程。currentState和targetState都由状态对象支持。

      判断拦截数据变化过程,用于实现对应的动画

      if (transitionState.currentState == LikedStates.Initial) {
          transitionState.targetState = LikedStates.Liked
      } else if (transitionState.currentState == LikedStates.Liked) {
          transitionState.targetState = LikedStates.Disappeared
      }

      开始显示的过度动画

      val transition = updateTransition(transitionState = transitionState, label = null)
      val alpha by transition.animateFloat(
          transitionSpec = {
             ...
          }
      ) {
          if (it == LikedStates.Liked) 1f else 0f
      }

      我们要实现有弹性的放大动画,所以利用graphicsLayer实现缩放

      graphicsLayer可以应用于

      • 缩放(scaleXscaleY
      • 旋转(rotationX、rotationY、rotationZ)
      • 不透明度(alpha
      • 阴影(shadowElevation、shape)
      • 剪裁(clip、shape)

      定义scale,XY

      1 :1放大所以定义一个就行

      val scale by transition.animateFloat(
          transitionSpec = {
             ....
          }
      ) {
        ...
      }

      创建浮动动画作为给定变换的一部分targetValueByState用作从目标状态到此动画的目标值的映射

      最后在定义三种状态里吗设置对应的参数

       when (it) {
              LikedStates.Initial -> 0f
              LikedStates.Liked -> 4f
              LikedStates.Disappeared -> 2f
          }

      完整代码

      @Suppress("TransitionPropertiesLabel")
      @Composable
       fun DoubleTapToLike() {
          var transitionState by remember {
              mutableStateOf(MutableTransitionState(LikedStates.Disappeared))
          }
      
          Box(
              Modifier
                  .fillMaxSize()
                  .pointerInput(Unit) {
                      detectTapGestures(
                          onDoubleTap = {
                              transitionState = MutableTransitionState(LikedStates.Initial)
                          }
                      )
                  }
          ) {
              if (transitionState.currentState == LikedStates.Initial) {
                  transitionState.targetState = LikedStates.Liked
              } else if (transitionState.currentState == LikedStates.Liked) {
                  transitionState.targetState = LikedStates.Disappeared
              }
      
              val transition = updateTransition(transitionState = transitionState, label = null)
              val alpha by transition.animateFloat(
                  transitionSpec = {
                      when {
                          LikedStates.Initial isTransitioningTo LikedStates.Liked ->
                              keyframes {
                                  durationMillis = 500
                                  0f at 0
                                  0.5f at 100
                                  1f at 225
                              }
                          LikedStates.Liked isTransitioningTo LikedStates.Disappeared ->
                              tween(durationMillis = 200)
                          else -> snap()
                      }
                  }
              ) {
                  if (it == LikedStates.Liked) 1f else 0f
              }
      
              val scale by transition.animateFloat(
                  transitionSpec = {
                      when {
                          LikedStates.Initial isTransitioningTo LikedStates.Liked ->
                              spring(dampingRatio = Spring.DampingRatioHighBouncy)
                          LikedStates.Liked isTransitioningTo LikedStates.Disappeared ->
                              tween(200)
                          else -> snap()
                      }
                  }
              ) {
                  when (it) {
                      LikedStates.Initial -> 0f
                      LikedStates.Liked -> 4f
                      LikedStates.Disappeared -> 2f
                  }
              }
      
              Icon(
                  Icons.Filled.Favorite,
                  "点赞",
                  Modifier
                      .align(Alignment.Center)
                      .graphicsLayer(
                          alpha = alpha,
                          scaleX = scale,
                          scaleY = scale
                      ),
                  tint = Color.Red
              )
          }
      }
      enum class LikedStates {
          Initial,
          Liked,
          Disappeared
      }

      效果图

      本文转自网络,如有侵权请联系客服删除。