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

相关推荐
RainCity4 小时前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
李斯维1 天前
从历史的角度看 Android 软件架构
android·架构·android jetpack
alexhilton2 天前
Android车载OS中的Remote Compose
android·kotlin·android jetpack
LinXunFeng8 天前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github
alexhilton8 天前
使用Android Archive进行打包
android·kotlin·android jetpack
Junerver11 天前
我写了一个 Compose Multiplatform 组件库,你可能会用到
kotlin·android jetpack
闪闪发亮的小星星12 天前
高斯光以及高斯光公式解释
笔记
cqbzcsq12 天前
CellFlow虚拟细胞论文阅读
论文阅读·人工智能·笔记·学习·生物信息
阿米亚波12 天前
【Windows】QEMU 启动 openEuler aarch64/arm64 架构系统 + 离线软件源
linux·windows·经验分享·笔记·架构·arm
自传.12 天前
尚硅谷 Vibe Coding|第三章(1) Claude Code深度使用与进阶技巧 学习笔记
笔记·学习·尚硅谷·vibecoding