可组合为位图而不显示它。

4

在使用经典的 View 时,很容易从视图中获取位图而无需显示它。我通过 LayoutInflater 创建了视图类,然后,由于它尚未附加到视图上,因此先对其进行测量。

我有以下扩展函数用于测量它并将视图绘制到位图上:

fun View.toBitmap(width, height): Bitmap {
    this.measure(
        View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
        View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY),
    )
    val bitmap = Bitmap.createBitmap(this.measuredWidth, this.measuredHeight, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    this.layout(0, 0, this.measuredWidth, this.measuredHeight)
    this.draw(canvas)
    return bitmap
}

当我使用 Composable 时,我无法从视图中导出位图。
我想象的是这样的:
class MyComposableView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
): AbstractComposeView(context, attrs, defStyleAttr) {
    @Composable
    override fun Content() {
        MyComposable()
    }
}

我所做的是使用应用程序上下文实例化一个 MyComposableView,然后尝试使用扩展函数 toBitmap 获取位图。 结果出现以下异常:
java.lang.IllegalStateException: Cannot locate windowRecomposer; View io.myapp.MyComposableView{f66ecdd V.E...... ......I. 0,0-0,0} is not attached to a window

我不明白的是为什么在通过布局填充器获取的视图中没有抛出异常,但在AbstractComposeView中会抛出异常。

编辑:截至2022年4月9日,似乎除使用传统XML布局外,没有其他解决方案。


你可以使用我的答案。它不需要使用XML。https://dev59.com/mcPra4cB1Zd3GeqPiYmM#74814850 - MH-Rouhani
1个回答

0
你可以通过以下步骤来实现这一点,而无需使用xml布局
BitmapComposable(
    onBitmapped = { bitmap ->
        // Do your operation
    },
    intSize = IntSize(500, 700) // Pixel size for output bitmap
) {
    // Composable that you want to convert to a bitmap
    // This scope is @Composable
    YourComposable()
}

1 - 复制这些函数:

请注意,这个可组合函数不会在屏幕上显示任何内容!

@Composable
fun BitmapComposable(
    onBitmapped: (bitmap: Bitmap) -> Unit = { _ -> },
    backgroundColor: Color = Color.Transparent,
    dpSize : DpSize,
    composable: @Composable () -> Unit
) {
    Column(modifier = Modifier
        .size(0.dp, 0.dp)
        .verticalScroll(
            rememberScrollState(), enabled = false
        )
        .horizontalScroll(
            rememberScrollState(), enabled = false
        )) {

        Box(modifier = Modifier.size(dpSize)) {
            AndroidView(factory = {
                ComposeView(it).apply {
                    setContent {
                        Box(modifier = Modifier.background(backgroundColor).fillMaxSize()) {
                            composable()
                        }
                    }
                }
            }, modifier = Modifier.fillMaxSize(), update = {
                it.run {
                    doOnLayout {
                        onBitmapped(drawToBitmap())
                    }
                }
            })
        }
    }

}

@Composable
fun BitmapComposable(
    onBitmapped: (bitmap: Bitmap) -> Unit = { _ -> },
    backgroundColor: Color = Color.Transparent,
    intSize : IntSize, // Pixel size for output bitmap
    composable: @Composable () -> Unit
) {
    val renderComposableSize = LocalDensity.current.run { intSize.toSize().toDpSize() }
    BitmapComposable(onBitmapped,backgroundColor,renderComposableSize,composable)
}

2 - 然后像这样使用:
BitmapComposable(
    onBitmapped = { bitmap ->
        // Do your operation
    },
    backgroundColor = Color.White,
    intSize = IntSize(500, 700) // Pixel size for output bitmap
) {
    // Composable that you want to convert to a bitmap
    // This scope is @Composable
    YourComposable()
}

你有以上答案的来源吗? - Mohammed Rousul
不,这是我通过反复试验和结合多种方法得到的。 - MH-Rouhani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接