Compose笔记(七十五)--withFrameNanos

这一节主要了解一下Compose中使用withFrameNanos,withFrameNanos是一个用于精确控制动画帧回调的核心函数,属于Compose动画系统的API。它允许使用者在每一帧动画渲染时获取当前时间戳,并基于时间计算动画进度,从而手动实现高性能的自定义动画逻辑。

API:

withFrameNanos:是一个挂起函数,用于在协程中以帧级精度执行动画逻辑,并返回当前帧的时间戳

栗子:

Kotlin 复制代码
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.translate

@Composable
fun WithFrameNanosDemo() {
    var xPosition by remember { mutableStateOf(0f) }

    LaunchedEffect(Unit) {
        var lastFrameTime = 0L
        while (true) {
            withFrameNanos { frameTime ->
                if (lastFrameTime != 0L) {
                    val deltaTime = (frameTime - lastFrameTime) / 1_000_000_000f
                    xPosition += 300 * deltaTime
                    if (xPosition > 1000f) xPosition = 0f
                }
                lastFrameTime = frameTime
            }
        }
    }

    Canvas(modifier = Modifier.fillMaxSize()) {
        translate(left = xPosition) {
            drawCircle(Color.Cyan, radius = 60f, center = Offset(200f, size.height / 2))
        }
    }
}
Kotlin 复制代码
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.unit.dp

@Composable
fun PhysicsWithFrameNanosDemo() {
    data class BallState(
        val x: Float = 100f,
        val y: Float = 200f,
        val vx: Float = 12f,
        val vy: Float = 0f,
    )

    val ball = remember { mutableStateOf(BallState()) }
    val radius = 40.dp.value

    LaunchedEffect(Unit) {
        var lastTime = 0L
        val gravity = 9.8f * 50
        val bounce = 0.8f

        while (true) {
            withFrameNanos { frameTime ->
                if (lastTime == 0L) {
                    lastTime = frameTime
                    return@withFrameNanos
                }

                val dt = (frameTime - lastTime) / 1_000_000_000f
                lastTime = frameTime
                var (x, y, vx, vy) = ball.value
                vy += gravity * dt
                x += vx
                y += vy

                val maxX = 1000f - radius * 2
                val maxY = 2000f - radius * 2

                if (x < 0 || x > maxX) vx *= -bounce
                if (y > maxY) {
                    vy *= -bounce
                    y = maxY
                }

                ball.value = BallState(x, y, vx, vy)
            }
        }
    }

    Canvas(modifier = Modifier.fillMaxSize()) {
        translate(ball.value.x, ball.value.y) {
            drawCircle(Color.Magenta, radius)
        }
    }
}

注意

1 必须在协程中调用

2 避免阻塞主线程

3 时间单位转换 frameTimeNanos是纳秒(1e-9 秒),通常需要转换为毫秒或秒

相关推荐
星恒随风21 小时前
C++ 类和对象入门(二):默认成员函数、构造函数和析构函数详解
开发语言·c++·笔记·学习
问心无愧051321 小时前
ctf show web入门102
android·java·前端·笔记
じ☆冷颜〃1 天前
Picard-Lindelöf 定理的多视角证明、推广与加权范数方法
经验分享·笔记·线性代数·数学建模
NULL指向我1 天前
TMS320F28379D笔记2:空项目文件+头文件添加
笔记
`流年づ1 天前
人工智能学习笔记-KNN
人工智能·笔记·学习
sheeta19981 天前
LeetCode 补拙笔记 日期:2026.06.07 题目:283. 移动零
笔记·算法·leetcode
xian_wwq1 天前
【学习笔记】「大模型安全:攻击面演化史」第 01 篇 Prompt Injection
笔记·学习·prompt
chnyi6_ya1 天前
论文阅读笔记:VChain: Chain-of-Visual-Thought for Reasoning in Video Generation
论文阅读·笔记
vortex51 天前
CheatMD:让 Markdown 笔记变成可执行的交互式命令
笔记·网络安全·markdown
じ☆冷颜〃1 天前
Picard–Lindelöf定理在CS中的应用:理论框架与算法基础
人工智能·经验分享·笔记·算法·机器学习