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

相关推荐
sakiko_6 小时前
Swift学习笔记42-SwiftUI的属性包装器(讲解+面试)
笔记·学习·ios·swiftui·swift
自小吃多7 小时前
器件移动、旋转、镜像、对齐、等间距操作笔记
笔记·嵌入式硬件
存在morning8 小时前
【Paimon 学习笔记 三】工作流程:Paimon 的批写、流写、批读与流读
笔记·学习
老当益壮梁奶奶9 小时前
Linux软件编程学习笔记(八):进程间通信详解(1)
linux·c语言·笔记·学习·算法
weixin_4660681110 小时前
《十分钟冥想》精读笔记(上):每天10分钟,给大脑做一次“系统减负”
笔记
凯尔萨厮11 小时前
Java学习笔记十(注解)
java·笔记·学习
一条破秋裤13 小时前
STM32 学习笔记:GPIO 输出实验——LED 闪烁、流水灯与蜂鸣器
笔记·stm32·学习
存在morning13 小时前
【Paimon 学习笔记 二】存储架构:快照、manifest、LSM 树、bucket
笔记·学习·架构
双眼鈹13 小时前
周报8.31
笔记·学习
打团从来人不齐14 小时前
Linux服务器搭建笔记-008:台式机共享WIFI
linux·服务器·笔记