jetpack compose blendMode 或 PorterDuff.Mode DST_IN
jetpack compose blendMode or PorterDuff.Mode DST_IN
我有一个模糊的背景位图和一个可水平滚动的行。我想实现的是背景图片必须只在行项目区域可见...
我尝试将 DST_IN 与混合模式一起应用,但没有成功。有什么想法可以在 Jetpack Compose 中实现吗?
我想要实现的是这个
我想要一个模糊版本的背景图像,它只在行项目中可见,这样滚动时它看起来就像行项目上的光泽镜面背景
您要么需要将 alpha 设置为小于 1f
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.DstIn
)
}
}
或者在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.DstIn
)
restoreToCount(checkPoint)
}
您可以查看此 tutorial 以了解有关混合模式的更多信息。
将 alpha 设置为小于 1f 可能看起来像是一种 hack,但 Image 的 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
}
}
并为 Image
创建图层
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()
}
}
}
}
}
我有一个模糊的背景位图和一个可水平滚动的行。我想实现的是背景图片必须只在行项目区域可见...
我尝试将 DST_IN 与混合模式一起应用,但没有成功。有什么想法可以在 Jetpack Compose 中实现吗?
我想要实现的是这个
我想要一个模糊版本的背景图像,它只在行项目中可见,这样滚动时它看起来就像行项目上的光泽镜面背景
您要么需要将 alpha 设置为小于 1f
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.DstIn
)
}
}
或者在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.DstIn
)
restoreToCount(checkPoint)
}
您可以查看此 tutorial 以了解有关混合模式的更多信息。
将 alpha 设置为小于 1f 可能看起来像是一种 hack,但 Image 的 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
}
}
并为 Image
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()
}
}
}
}
}