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 秒),通常需要转换为毫秒或秒

相关推荐
GlueNa2SiO32 小时前
第十八章 Linux故障排查与恢复
linux·服务器·笔记·学习
xian_wwq3 小时前
【学习笔记】Context Engineering,AI Agent 真正的内存管理-4/16
笔记·学习·context
疯狂打码的少年4 小时前
【数据结构】队列:定义、顺序队列与链式队列
数据结构·笔记
LeoZY_7 小时前
LinkScope 使用笔记:基于 OpenOCD 的通用硬件芯片调试助手
笔记·单片机·嵌入式硬件·开源软件
不会代码的小猴7 小时前
标准模板库(STL)
开发语言·c++·笔记·算法
爱莉希雅&&&7 小时前
K8s NFS+StorageClass+PV/PVC+Deployment 实战笔记
笔记·容器·kubernetes
影寂ldy8 小时前
SQL 索引(Index)完整笔记
数据库·笔记·sql
GlueNa2SiO38 小时前
06-Docker存储与数据持久化
笔记·学习·docker
上下求索,莫负韶华10 小时前
切面学习笔记
笔记·python·学习
测试运维日常笔记10 小时前
Unix/Linux 系统软件包管理笔记
linux·笔记·unix