今年的疫情蠻嚴重的,希望大家都過得安好,希望疫情快點過去,能回到一些線下技術聚會的時光~
今天目標:了解 Compose UI 上 的 animation 位移 可以怎麼實作。
如果今天我們想實作一個圖片移動,從左下角移動到右上角,應該怎麼實作呢?思考的方式,是先定義出一個變化的時間,這個時間的數值會從 0 到1,然後讓畫面每隔一個時間就變化一次,從0的時間 到 1的時間,每個時間的畫面應該如何呈現,就可以完成動畫。
時間數值也可以不用0到1,可以有很多不同的變化,畫面變化跟呈現就是數學,將畫面想像成x,y軸,時間變化的0到1這個過程中,如何讓圖畫到你想要指定的位置上。
我參考了範例後改寫出下面的程式碼。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val animationState =remember{mutableStateOf(false)}
BoxWithConstraints(
modifier = Modifier
.fillMaxSize()
.background(color = Color.Black)){
MovingDemo(
isMovingEnabled = animationState.value,
maxWidth = maxWidth,
maxHeight = maxHeight
)
LaunchButton(
animationState = animationState.value,
onToggleAnimationState ={animationState.value = !animationState.value})}
// 首先還是要先宣告圖跟按鈕
}
}
@Composable
fun MovingDemo(
isMovingEnabled: Boolean,
maxWidth: Dp,
maxHeight: Dp
) {
val modifier: Modifier
val emojiSize = 100.dp
if (!isMovingEnabled) {
modifier = Modifier.offset(
y = maxHeight - emojiSize, x = maxWidth
)
// 如果確定開始執行後就每次改變 x與y的數值
} else {
val infiniteTransition = rememberInfiniteTransition()
// 記住動畫的變數
val xPositionState = infiniteTransition.animateFloat(
initialValue = 0f, // 初始值
targetValue = 1f, // 最後目標值
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 2000,
easing = LinearOutSlowInEasing
)
)
// 每2000 millis seconds 變化一次,變化採 LinearOutSlowInEasing的方式
)
modifier = Modifier.offset(
x = (maxWidth - emojiSize ) * xPositionState.value,
y = (maxHeight - emojiSize) - (maxHeight - emojiSize) * xPositionState.value,
)
// 定義 x 與 y值的變化
}
Image(
modifier = modifier
.width(emojiSize)
.height(emojiSize),
painter = painterResource(id = R.drawable.horse),
contentDescription = "A horse",
)
// 如Day 7 一樣 宣告一個Image
}
執行效果如上圖。
動畫的概念大多如此,可以思考譬如需要有一些特殊的畫面變化,如從下而上的 emoji 左右飄浮,或是從上而下如下雪般的雪花之類的,總之動畫的內容實在太多了,而且博大精深,可以探討的東西太多,所以今天會是最後一篇~
如果都搞懂了,我們就明天下個單元見!
參考資料:
https://www.youtube.com/watch?v=7yY2OocGiQU&ab_channel=AndroidDevelopers
https://www.youtube.com/watch?v=hLERtWC1THw&ab_channel=CodingWithMitch
https://github.com/mitchtabian/ComposePlayground/blob/animation-beta01-sample/app/src/main/java/com/codingwithmitch/composeplayground/ui/MainActivity.kt
本文同步發表在 Medium 上: 文章連結