【问题标题】:How to make Compose render my custom Shape?如何让 Compose 呈现我的自定义形状?
【发布时间】:2023-02-11 18:25:37
【问题描述】:

我有这个 Composable,它在后面绘制一些带有自定义 Shape 的文本:

@Composable
fun TextWithIcon(text: String, icon: Shape) {
    Box(Modifier.size(48.dp)
        .border(1.dp, MaterialTheme.colors.secondaryVariant)
        .background(MaterialTheme.colors.background)
        .padding(4.dp)
        .border(2.dp, MaterialTheme.colors.secondaryVariant, icon)
        .padding(4.dp), contentAlignment = Alignment.Center) {
        Text(text, color = MaterialTheme.colors.onBackground)
    }
}

每当我调用它时,Compose 都会在内部抛出一个异常,甚至没有提及我的代码:

Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Failed to Image::makeFromBitmap Bitmap(_ptr=0x249bafa64c0)
    at org.jetbrains.skia.Image$Companion.makeFromBitmap(Image.kt:115)
    at androidx.compose.ui.graphics.SkiaBackedCanvas.drawImageRect-cI72Soc(SkiaBackedCanvas.skiko.kt:210)
    at androidx.compose.ui.graphics.SkiaBackedCanvas.drawImageRect-HPBpro0(SkiaBackedCanvas.skiko.kt:185)
    at androidx.compose.ui.graphics.drawscope.CanvasDrawScope.drawImage-AZ2fEMs(CanvasDrawScope.kt:263)
    at androidx.compose.ui.node.LayoutNodeDrawScope.drawImage-AZ2fEMs(LayoutNodeDrawScope.kt)
    at androidx.compose.ui.graphics.drawscope.DrawScope.drawImage-AZ2fEMs$default(DrawScope.kt:510)
    at androidx.compose.foundation.BorderKt$drawGenericBorder$3.invoke(Border.kt:318)
    at androidx.compose.foundation.BorderKt$drawGenericBorder$3.invoke(Border.kt:315)
    at androidx.compose.ui.draw.DrawContentCacheModifier.draw(DrawModifier.kt:218)
    at androidx.compose.ui.node.DrawEntity.draw(DrawEntity.kt:98)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:320)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:310)
    at androidx.compose.ui.node.LayoutNode.draw$ui(LayoutNode.kt:839)
    at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:90)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:318)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:310)
    at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:139)
    at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:48)
    at androidx.compose.foundation.Background.draw(Background.kt:107)
    at androidx.compose.ui.node.DrawEntity.draw(DrawEntity.kt:98)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:320)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:310)
    at androidx.compose.ui.node.LayoutNode.draw$ui(LayoutNode.kt:839)
    at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:90)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:318)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:310)
    at androidx.compose.ui.node.LayoutNode.draw$ui(LayoutNode.kt:839)
    at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:90)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:318)
    at androidx.compose.ui.node.LayoutNodeWrapper.access$drawContainedDrawModifiers(LayoutNodeWrapper.kt:60)
    at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:340)
    at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:339)
    at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2117)
    at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:113)
    at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui(OwnerSnapshotObserver.kt:78)
    at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:339)
    at androidx.compose.ui.node.LayoutNodeWrapper$invokeOnCanvasInstance$1.invoke(LayoutNodeWrapper.kt:161)
    at androidx.compose.ui.node.LayoutNodeWrapper$invokeOnCanvasInstance$1.invoke(LayoutNodeWrapper.kt:161)
    at androidx.compose.ui.platform.SkiaLayer.performDrawLayer(SkiaLayer.skiko.kt:264)
    at androidx.compose.ui.platform.SkiaLayer.drawLayer(SkiaLayer.skiko.kt:225)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:305)
    at androidx.compose.ui.node.LayoutNode.draw$ui(LayoutNode.kt:839)
    at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:90)
    at androidx.compose.ui.node.LayoutNodeWrapper.drawContainedDrawModifiers(LayoutNodeWrapper.kt:318)
    at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:310)
    at androidx.compose.ui.node.LayoutNode.draw$ui(LayoutNode.kt:839)
    at androidx.compose.ui.platform.SkiaBasedOwner.draw(SkiaBasedOwner.skiko.kt:347)
    at androidx.compose.ui.ComposeScene.render(ComposeScene.skiko.kt:419)
    at androidx.compose.ui.awt.ComposeLayer$1$onRender$1.invoke(ComposeLayer.desktop.kt:316)
    at androidx.compose.ui.awt.ComposeLayer$1$onRender$1.invoke(ComposeLayer.desktop.kt:315)
    at androidx.compose.ui.awt.ComposeLayer.catchExceptions(ComposeLayer.desktop.kt:107)
    at androidx.compose.ui.awt.ComposeLayer.access$catchExceptions(ComposeLayer.desktop.kt:85)
    at androidx.compose.ui.awt.ComposeLayer$1.onRender(ComposeLayer.desktop.kt:315)
    at org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:510)
    at org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
    at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invokeSuspend(Direct3DRedrawer.kt:40)
    at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invoke(Direct3DRedrawer.kt)
    at org.jetbrains.skiko.redrawer.Direct3DRedrawer$frameDispatcher$1.invoke(Direct3DRedrawer.kt)
    at org.jetbrains.skiko.FrameDispatcher$job$1.invokeSuspend(FrameDispatcher.kt:33)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
    Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@119c1b04, SwingDispatcher@56da22a8]

每种形状都会发生这种情况,即使是甚至不绘制任何东西的形状也是如此:

TextWithIcon("Hi", GenericShape { _, _ -> })

奇怪的是,我确定我已经看到这段代码起作用并绘制了形状。我只是不确定从那时到现在我做了什么改变,这打破了它。

Modifier 中删除除(第二个)边框之外的所有内容都无济于事,仍然会崩溃。同时删除 Box 内容然后修复崩溃,大概是因为 Compose 知道该元素是空的,甚至不会尝试渲染它......

我如何让它工作?

【问题讨论】:

  • 您的代码在 androidx.compose.ui:ui-graphics:1.3.3 下运行良好
  • 我目前正在使用 Compose Desktop 1.2.0。我看到 1.3 即将发布,我会检查一下。
  • @pushpull 我升级到 Compose Desktop 1.3.0,同样的错误。
  • 我在 compose 桌面上试过它,它在 1.3.0 上运行良好。 snipboard.io/CI4uqB.jpg

标签: kotlin compose-desktop


【解决方案1】:

该问题似乎与您的 TextWithIcon 可组合项的图标参数有关。具体来说,当 Compose 尝试使用 Skia 图形库绘制形状的边框时会出现问题,而 Skia 图形库是 Compose 在后台用于绘制的。

您看到的错误消息提到了从位图创建图像的问题。这表明您作为图标参数传入的形状的位图表示可能存在问题。

要尝试的一件事是使用内置的 Shape 实现,例如 CircleShape 或 RoundedCornerShape,看看问题是否仍然存在。如果问题随着内置形状消失,则可能是您创建自定义形状的方式有问题。

或者,您可以尝试将对 TextWithIcon 的调用包装在 Surface 可组合项中,这会创建一个绘图图面来处理 Compose 的底层图形。这可能有助于隔离问题并提供有关问题所在的更多信息。

最后,值得注意的是,您看到的错误消息是内部 Compose 错误,可能与您的代码没有直接关系。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-17
    • 1970-01-01
    • 2017-09-21
    • 2019-12-17
    • 2017-12-08
    • 2023-01-02
    • 1970-01-01
    • 2021-04-11
    相关资源
    最近更新 更多