Thr*_*ian 7 android canvas porter-duff android-jetpack-compose
我下载了图像,最初即使它们是png,它们也有浅灰色和深灰色的矩形,这些矩形不透明并删除了它们。
并使用此示例代码进行检查,将原始代码中的可绘制对象替换为下面的可绘制对象,我得到结果
看起来它可以与 Android View 一起使用,但是当我使用 Jetpack Canvas 作为
androidx.compose.foundation.Canvas(modifier = Modifier.size(500.dp),
onDraw = {
drawImage(imageBitmapDst)
drawImage(imageBitmapSrc, blendMode = BlendMode.SrcIn)
})
Run Code Online (Sandbox Code Playgroud)
BlendMode.SrcIn 在黑色矩形上绘制蓝色矩形,其他模式也不会返回正确的结果。BlendMode.SrcOut 返回黑屏。
并使用 2 张图像堆叠在一起Box
val imageBitmapSrc: ImageBitmap = imageResource(id = R.drawable.c_src)
val imageBitmapDst: ImageBitmap = imageResource(id = R.drawable.c_dst)
Box {
Image(bitmap = imageBitmapSrc)
Image(
bitmap = imageBitmapDst,
colorFilter = ColorFilter(color = Color.Unspecified, blendMode = BlendMode.SrcOut)
)
}
Run Code Online (Sandbox Code Playgroud)
仅蓝色 src 矩形可见。
也尝试过Painter,但也无法使其工作
val imageBitmapSrc: ImageBitmap = imageResource(id = R.drawable.c_src)
val imageBitmapDst: ImageBitmap = imageResource(id = R.drawable.c_dst)
val blendPainter = remember {
object : Painter() {
override val intrinsicSize: Size
get() = Size(imageBitmapSrc.width.toFloat(), imageBitmapSrc.height.toFloat())
override fun DrawScope.onDraw() {
drawImage(imageBitmapDst, blendMode = BlendMode.SrcOut)
drawImage(imageBitmapSrc)
}
}
}
Image(blendPainter)
Run Code Online (Sandbox Code Playgroud)
Jetpack Compose应该如何使用Blend或模式?PorterDuff
从 1.4.1 或更高版本开始,您可以分配
Modifier.graphicsLayer {
compositingStrategy = CompositingStrategy.Offscreen
}
Run Code Online (Sandbox Code Playgroud)
或Canvas在graphicsLayer之后的任何绘制修改器能够正确使用BlendModes,
解决问题的另一种方法是添加
.graphicsLayer(alpha = 0.99f)以Modifier确保屏幕外缓冲区
@Composable
fun DrawWithBlendMode() {
val imageBitmapSrc = ImageBitmap.imageResource(
LocalContext.current.resources,
R.drawable.composite_src
)
val imageBitmapDst = ImageBitmap.imageResource(
LocalContext.current.resources,
R.drawable.composite_dst
)
Canvas(
modifier = Modifier
.fillMaxSize()
// Provide a slight opacity to for compositing into an
// offscreen buffer to ensure blend modes are applied to empty pixel information
// By default any alpha != 1.0f will use a compositing layer by default
.graphicsLayer(alpha = 0.99f)
) {
val dimension = (size.height.coerceAtMost(size.width) / 2f).toInt()
drawImage(
image = imageBitmapDst,
dstSize = IntSize(dimension, dimension)
)
drawImage(
image = imageBitmapSrc,
dstSize = IntSize(dimension, dimension),
blendMode = BlendMode.SrcOut
)
}
}
Run Code Online (Sandbox Code Playgroud)
结果
或者在 Canvas 中添加一个图层就可以了
with(drawContext.canvas.nativeCanvas) {
val checkPoint = saveLayer(null, null)
// Destination
drawImage(
image = dstImage,
srcSize = IntSize(canvasWidth / 2, canvasHeight / 2),
dstSize = IntSize(canvasWidth, canvasHeight),
)
// Source
drawImage(
image = srcImage,
srcSize = IntSize(canvasWidth / 2, canvasHeight / 2),
dstSize = IntSize(canvasWidth, canvasHeight),
blendMode = blendMode
)
restoreToCount(checkPoint)
}
Run Code Online (Sandbox Code Playgroud)
我在这里创建了一些应用混合模式的教程
我整整一周都因类似的问题而感到沮丧,但是您的问题帮助我找到了如何使其发挥作用的解决方案。
我正在使用撰写1.0.0
就我而言,我使用双缓冲之类的东西,而不是直接在画布上绘图 - 只是作为一种解决方法。
Canvas(modifier = Modifier.fillMaxWidth().fillMaxHeight()) {
// First I create bitmap with real canva size
val bitmap = ImageBitmap(size.width.toInt(), size.height.toInt())
// here I'm creating canvas of my bitmap
Canvas(bitmap).apply {
// here I'm driving on canvas
}
// here I'm drawing my buffered image
drawImage(bitmap)
}
Run Code Online (Sandbox Code Playgroud)
在里面Canvas(bitmap)我使用drawPath、drawText等与油漆:
val colorPaint = Paint().apply {
color = Color.Red
blendMode = BlendMode.SrcAtop
}
Run Code Online (Sandbox Code Playgroud)
以这种方式BlendMode工作正常 - 我已经尝试了很多模式,一切都按预期工作。
我不知道为什么这不能直接在可组合画布上工作,但我的解决方法对我来说效果很好。
在研究了 Image 的 Painter 的源代码后,我发现 Android 团队也使用 alpha 技巧来决定是否创建图层
在Painter
private fun configureAlpha(alpha: Float) {
if (this.alpha != alpha) {
val consumed = applyAlpha(alpha)
if (!consumed) {
if (alpha == DefaultAlpha) {
// Only update the paint parameter if we had it allocated before
layerPaint?.alpha = alpha
useLayer = false
} else {
obtainPaint().alpha = alpha
useLayer = true
}
}
this.alpha = alpha
}
}
Run Code Online (Sandbox Code Playgroud)
并适用于此
fun DrawScope.draw(
size: Size,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
) {
configureAlpha(alpha)
configureColorFilter(colorFilter)
configureLayoutDirection(layoutDirection)
// b/156512437 to expose saveLayer on DrawScope
inset(
left = 0.0f,
top = 0.0f,
right = this.size.width - size.width,
bottom = this.size.height - size.height
) {
if (alpha > 0.0f && size.width > 0 && size.height > 0) {
if (useLayer) {
val layerRect = Rect(Offset.Zero, Size(size.width, size.height))
// TODO (b/154550724) njawad replace with RenderNode/Layer API usage
drawIntoCanvas { canvas ->
canvas.withSaveLayer(layerRect, obtainPaint()) {
onDraw()
}
}
} else {
onDraw()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5091 次 |
| 最近记录: |