如何在 SkikoKotlin MPP 绑定到 Skia上制作基本动画?

问题描述

使用 Skiko 和 Kotlin,我想制作一个基本动画:一个 0 到 100 的计数器,每秒自动更新文本。 我设法做到了,但它有一个问题,每次重新绘制窗口时它都会闪烁。 代码如下:

import kotlinx.coroutines.*
import org.jetbrains.skija.*
import org.jetbrains.skiko.*
import javax.swing.*

public fun main() {
    val window = SkiaWindow().apply {
        layer.renderer = CounterRenderer()
        setSize(400,175)
        isVisible = true
        defaultCloSEOperation = WindowConstants.EXIT_ON_CLOSE
    }
    GlobalScope.launch {
        for (i in 0..100) {
            delay(1000)
            window.layer.repaint()
        }
    }
}

public class CounterRenderer : SkiaRenderer {
    private lateinit var canvas: Canvas
    private var counter = 0

    override fun onInit() {
    }

    override fun ondispose() {
    }

    override fun onReshape(width: Int,height: Int) {
    }

    override fun onRender(canvas: Canvas,width: Int,height: Int) {
        this.canvas = canvas

        val typeface = Typeface.makeFromName("Roboto",FontStyle.norMAL)
        val fontSize = 30F
        val font = Font(typeface,fontSize)

        val paint = Paint().setColor(0XFF000000.toInt())
        canvas.drawString("Counter: ${counter++}",10F,50F,font,paint)
    }
}

我曾尝试使用skija 或skiko 搜索动画示例,但没有成功。 如果您能给我一些例子,我将不胜感激。

解决方法

在浏览 Android Compose 代码后,尤其是这个类: ComposeLayer。 我终于可以使用此代码了:

import kotlinx.coroutines.*
import org.jetbrains.skija.*
import org.jetbrains.skiko.*
import javax.swing.*

public fun main() {
    val window = SkiaWindow().apply {
        layer.renderer = CounterRenderer()
        setSize(400,175)
        isVisible = true
        defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE
    }
    GlobalScope.launch(Dispatchers.Main) {
        for (i in 0..100) {
            delay(500)
            window.layer.redrawLayer()
        }
    }
}

public class CounterRenderer : SkiaRenderer {
    private var counter = 0
    private val typeface = Typeface.makeFromName("Roboto",FontStyle.NORMAL)
    private val fontSize = 30F
    private val font = Font(typeface,fontSize)
    private val paint = Paint().setColor(0XFF000000.toInt())

    override fun onInit() {
    }

    override fun onDispose() {
    }

    override fun onReshape(width: Int,height: Int) {
    }

    override fun onRender(canvas: Canvas,width: Int,height: Int) {
        canvas.drawString("Counter: ${counter++}",10F,50F,font,paint)
    }
}

要运行此代码,您需要安装特定的 Main Dispatcher,在本例中是通过将其添加到 gradle 配置中:

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.3.9")