📌  相关文章
📜  在 Android Jetpack Compose 中创建触摸弹跳动画

📅  最后修改于: 2022-05-13 01:55:12.634000             🧑  作者: Mango

在 Android Jetpack Compose 中创建触摸弹跳动画

先决条件:

  • Kotlin 基础知识
  • Jetpack Compose 基础知识

在这篇文章中,我们将看看如何创建用户点击任何东西时的弹跳动画,进一步可以根据应用程序的使用进行扩展。这是演示动画的示例 gif。

分步实施

第 1 步:创建一个新项目(或在现有 Compose 项目中使用它)

要在 Android Studio Canary 版本中创建新项目,请参阅文章如何使用 Jetpack Compose 在 Android Studio Canary 版本中创建新项目。



第 2 步:使用 MainActivity.kt

创建一个存储状态(已发布/已按下)的枚举类。

Kotlin
enum class BounceState { Pressed, Released }


Kotlin
var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
val transition = updateTransition(targetState = currentState, label = "animation")
 
val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
) { state ->
 
        // When the item is pressed , reduce
          // its size by 5% or make its size 0.95
          // of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
              // make it of its original size
            1f
      }
}


Kotlin
// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
      }
}


Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.shaun.bounceanimation.ui.theme.BounceAnimationTheme
 
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BounceAnimationTheme {
                Surface(color = MaterialTheme.colors.background) {
                    Bounce()
                }
            }
        }
    }
}
 
enum class BounceState { Pressed, Released }
 
@Preview(showBackground = true)
@Composable
fun Bounce() {
    var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
    val transition = updateTransition(targetState = currentState, label = "animation")
    val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
    ) { state ->
 
        // When the item is pressed ,reduce its size
          // by 5% or make its size 0.95 of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
             // make it of its original size
            1f
        }
    }
 
// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
 
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
        }
    }
}



第 3 步:添加动画

创建一个可组合函数Bounce,添加如下代码

科特林

var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
val transition = updateTransition(targetState = currentState, label = "animation")
 
val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
) { state ->
 
        // When the item is pressed , reduce
          // its size by 5% or make its size 0.95
          // of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
              // make it of its original size
            1f
      }
}

然后使用 pointerInputScope 修饰符检测手势并应用动画,同时将以下代码添加到 Bounce 组合中。

科特林

// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
      }
}


我们已经完成了。这是MainActivity.kt文件的最终代码。

科特林

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.shaun.bounceanimation.ui.theme.BounceAnimationTheme
 
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BounceAnimationTheme {
                Surface(color = MaterialTheme.colors.background) {
                    Bounce()
                }
            }
        }
    }
}
 
enum class BounceState { Pressed, Released }
 
@Preview(showBackground = true)
@Composable
fun Bounce() {
    var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
    val transition = updateTransition(targetState = currentState, label = "animation")
    val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
    ) { state ->
 
        // When the item is pressed ,reduce its size
          // by 5% or make its size 0.95 of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
             // make it of its original size
            1f
        }
    }
 
// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
 
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
        }
    }
}

输出:

从这里获取完整的项目。

想要一个更快节奏和更具竞争力的环境来学习 Android 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!