在 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 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!