成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手把手教你用 Jetpack Compose 做會動的點贊按鈕!

開發 前端
畫就像做菜,得分步驟!我們把這個效果拆成:1. 圓形背景「膨脹」(像吹氣球??)2. 大拇指「閃現」3. 小圓點點「炸煙花」(最炫的part!)4. 所有元素「優雅退場」。

??? 四步搞定動畫魔法

步驟1:把動畫拆成「番茄炒蛋」

畫就像做菜,得分步驟!我們把這個效果拆成:

1. 圓形背景「膨脹」(像吹氣球??)

2. 大拇指「閃現」

3. 小圓點點「炸煙花」(最炫的part!)

4. 所有元素「優雅退場」

// 用枚舉告訴代碼:「現在該哪一步了?」
enum class AnimationState {
    IDLE,          // 靜止狀態
    CIRCLE_GROW,   // 背景圓圈擴散
    THUMB_JUMP,    // 點贊圖標彈跳
    DOT_EXPLOSION, // 小圓點爆發
    FINISH         // 動畫結束
}

步驟2:用「時間管理器」控制動畫流程

Jetpack Compose 的 Transition 就像動畫導演??,它會說:「3秒后該放大圓圈了,5秒后彈出大拇指...」

@Composable
fun LikeButton(isLiked: Boolean) {
    // ?? 核心狀態控制
    var isLiked by remember { mutableStateOf(false) }
    var currentState by remember { mutableStateOf(AnimationState.IDLE) }

    // ?? 單位轉換(解決DP/PX混亂問題!)
    val density = LocalDensity.current
    val maxCircleSize = 48.dp
    val maxCirclePx = with(density) { maxCircleSize.toPx() }

    // ?? 動畫過渡控制
    val transition = updateTransition(currentState, label = "LikeTransition")

    // ? 定義動畫數值
    // 背景圓圈半徑
    val circleRadius by transition.animateFloat(
        transitionSpec = {
            when {
                AnimationState.IDLE isTransitioningTo AnimationState.CIRCLE_GROW ->
                    tween(300, easing = FastOutSlowInEasing)

                else -> snap()
            }
        }, label = "circleRadius"
    ) { state ->
        when (state) {
            AnimationState.CIRCLE_GROW -> maxCirclePx
            else -> 0f
        }
    }

    // ?? 大拇指圖標動畫(彈跳效果)
    val thumbScale by transition.animateFloat(
        transitionSpec = {
            keyframes {
                durationMillis = 600
                0f at 0 with LinearEasing
                1.2f at 150
                1f at 300
            }
        }, label = "thumbScale"
    ) { state ->
        when (state) {
            AnimationState.THUMB_JUMP -> 1f
            AnimationState.FINISH -> 1f
            AnimationState.IDLE -> 1f// 確保初始狀態也顯示
            else -> 0f
        }
    }

    // ?? 爆炸小圓點
    val dotsProgress by transition.animateFloat(
        transitionSpec = { tween(500) },
        label = "dotsProgress"
    ) { state ->
        when (state) {
            AnimationState.DOT_EXPLOSION -> 1f
            else -> 0f
        }
    }

    // ?? 點擊觸發動畫
    LaunchedEffect(isLiked) {
        if (isLiked) {
            currentState = AnimationState.CIRCLE_GROW
            delay(300)
            currentState = AnimationState.THUMB_JUMP
            delay(300)
            currentState = AnimationState.DOT_EXPLOSION
            delay(800)
            currentState = AnimationState.FINISH
        } else {
            currentState = AnimationState.IDLE
        }
    }
    
    // 繪制界面(下一步講)
}

步驟3:畫一個「會動的圖層」

用 Canvas 和 Box 像PS一樣疊加圖層:背景圈圈在下,點贊圖標居中,小圓點環繞四周。

// ?? 繪制界面
Box(
    modifier = Modifier
        .size(72.dp)
        .clickable { isLiked = !isLiked },
    contentAlignment = Alignment.Center
) {
    // 背景擴散圓圈
    if (currentState != AnimationState.IDLE) {
        Canvas(modifier = Modifier.fillMaxSize()) {
            drawCircle(
                color = Color.Red.copy(alpha = 0.2f),
                radius = circleRadius,
                style = Stroke(width = 2.dp.toPx())
            )
        }
    }

    // 大拇指圖標(帶彈跳)
    Icon(
        imageVector = Icons.Default.ThumbUp,
        contentDescription = "Like",
        modifier = Modifier
            .size(32.dp)
            .graphicsLayer {
                scaleX = thumbScale
                scaleY = thumbScale
            },
        tint = if (isLiked) Color.Red else Color.Gray
    )

    // 爆炸小圓點
    if (dotsProgress > 0) {
        val angles = listOf(0f, 45f, 90f, 135f, 180f, 225f, 270f, 315f)
        val radius = with(LocalDensity.current) { 48.dp.toPx() } * dotsProgress
        val dotRadius = with(LocalDensity.current) { 4.dp.toPx() }

        Canvas(modifier = Modifier.fillMaxSize()) {
            val center = Offset(size.width / 2, size.height / 2)

            angles.forEach { angle ->
                val radians = Math.toRadians(angle.toDouble())
                val x = center.x + radius * cos(radians).toFloat()
                val y = center.y + radius * sin(radians).toFloat()
                    
                drawCircle(
                    color = Color(0xFFFF6B6B).copy(alpha = 1 - dotsProgress),
                    radius = dotRadius,
                    center = Offset(x, y)
                )
            }
        }
    }
}

步驟4:加億點點細節

  • ? 彈性動畫:讓圓圈放大時有「彈簧感」
  • ? 漸隱效果:退場時用 alpha 動畫讓元素淡出

圖片圖片

?? 學完后你能舉一反三

? 替換成愛心、星星?等不同圖標

? 把小圓點改成小星星、花瓣??

? 調整顏色、動畫時長、彈跳幅度...

責任編輯:武曉燕 來源: 沐雨花飛碟
相關推薦

2011-03-28 16:14:38

jQuery

2021-08-09 13:31:25

PythonExcel代碼

2022-10-19 14:30:59

2021-02-04 09:00:57

SQLDjango原生

2021-02-06 14:55:05

大數據pandas數據分析

2022-08-04 10:39:23

Jenkins集成CD

2009-04-22 09:17:19

LINQSQL基礎

2021-05-10 06:48:11

Python騰訊招聘

2021-01-21 09:10:29

ECharts柱狀圖大數據

2021-01-08 10:32:24

Charts折線圖數據可視化

2012-01-11 13:40:35

移動應用云服務

2021-08-02 23:15:20

Pandas數據采集

2020-03-08 22:06:16

Python數據IP

2021-02-02 13:31:35

Pycharm系統技巧Python

2021-12-11 20:20:19

Python算法線性

2017-10-27 10:29:35

人臉識別UbuntuPython

2021-06-05 23:51:21

ECharts氣泡圖散點圖

2021-03-23 09:05:52

PythonExcelVlookup

2021-01-30 10:37:18

ScrapyGerapy網絡爬蟲

2009-08-27 18:10:58

PHP繪制3D圖形
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产91久久久久久 | 精品国产久| 91麻豆精品国产91久久久更新资源速度超快 | 日日艹夜夜艹 | 久久久久黑人 | 精品www| 一本一道久久a久久精品综合 | 精品久久久久久亚洲精品 | 国产美女久久久 | av日韩一区 | 日韩国产黄色片 | 成人在线免费网站 | 亚洲免费在线观看av | 狠狠亚洲| 久久在线免费 | 日韩视频a | 伊人中文字幕 | 手机av在线 | 国产成人精品一区二区三区在线 | 国产一区在线免费观看视频 | 亚洲福利一区二区 | 欧美操操操| 国产精品毛片无码 | 在线中文字幕视频 | 午夜精品一区二区三区在线观看 | 91久操视频| 亚洲一区二区三区免费 | 国产精品明星裸体写真集 | 亚洲精品久久久久中文字幕二区 | 麻豆a级片 | 毛片com | 国产线视频精品免费观看视频 | 日本天天操 | 日本中文字幕一区 | 国产视频91在线 | 嫩草视频在线看 | 精品在线一区 | 一区在线视频 | 日韩欧美在线观看 | 一级黄色裸片 | 一区二区三区视频在线观看 |