Day 21 Compose UI Animation III

今年的疫情蛮严重的,希望大家都过得安好,希望疫情快点过去,能回到一些线下技术聚会的时光~

今天目标:了解 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 上: 文章连结


<<:  <Day11> Contract — 取得指数(Index)资讯

>>:  【Day26】Function Component 生命周期 & Hook (´・∀・`)

为什麽要使用VPN?综合3款VPN推荐给大家

最近有朋友回中国内地工作,刚好问我有什麽VPN推荐一下给他,需要在内地能翻墙,连脸书就可以了,了解他...

JS ES6 箭头函式常见问题 DAY74

箭头函式常见问题 若要回传物件 需用一个括号包住 const fn = () => ({ da...

【zerojudge恶龙题】- c005: 10300 - Ecological Premium

这题对Python来说很友善,直接算就好了 每笔奖金算法 [(农场的面积/农场里动物的数目) * 农...

Day-06 Classification

昨天聊完如果要做资料 Regression(预测)的话,要给予基本的 Model + Data,并...

修改word 作者属性

删除作者 作法1 : 直接修改 删除作者,删掉,从这边删掉,按确定就可以了 作法2 : 移除档案属性...