No Compose, um objeto Painter
é usado para representar algo que pode ser desenhado
(uma substituição às APIs Drawable
definidas no Android) e influenciar
a medição e o layout do elemento combinável correspondente que está em uso. Um
BitmapPainter
usa um ImageBitmap
que pode desenhar um Bitmap
na tela.
Na maioria dos casos, o uso do painterResource()
acima retorna o painter correto
para o recurso (por exemplo, BitmapPainter
ou VectorPainter
). Para mais
informações sobre as diferenças entre os dois, leia a seção ImageBitmap x ImageVector.
Um Painter
é diferente de uma DrawModifier
, que é desenhado estritamente
nos limites fornecidos e não tem influência na medição ou no layout
do elemento combinável.
Para criar um painter personalizado, estenda a classe Painter
e implemente o
método onDraw
, que permite acesso a DrawScope
para desenhar gráficos
personalizados. Você também pode substituir o intrinsicSize
, que vai ser usado para
influenciar os elementos combinável em que está contido:
class OverlayImagePainter constructor( private val image: ImageBitmap, private val imageOverlay: ImageBitmap, private val srcOffset: IntOffset = IntOffset.Zero, private val srcSize: IntSize = IntSize(image.width, image.height), private val overlaySize: IntSize = IntSize(imageOverlay.width, imageOverlay.height) ) : Painter() { private val size: IntSize = validateSize(srcOffset, srcSize) override fun DrawScope.onDraw() { // draw the first image without any blend mode drawImage( image, srcOffset, srcSize, dstSize = IntSize( this@onDraw.size.width.roundToInt(), this@onDraw.size.height.roundToInt() ) ) // draw the second image with an Overlay blend mode to blend the two together drawImage( imageOverlay, srcOffset, overlaySize, dstSize = IntSize( this@onDraw.size.width.roundToInt(), this@onDraw.size.height.roundToInt() ), blendMode = BlendMode.Overlay ) } /** * Return the dimension of the underlying [ImageBitmap] as it's intrinsic width and height */ override val intrinsicSize: Size get() = size.toSize() private fun validateSize(srcOffset: IntOffset, srcSize: IntSize): IntSize { require( srcOffset.x >= 0 && srcOffset.y >= 0 && srcSize.width >= 0 && srcSize.height >= 0 && srcSize.width <= image.width && srcSize.height <= image.height ) return srcSize } }
Agora que temos o Painter
personalizado, podemos substituir qualquer imagem sobre a
imagem de origem da seguinte maneira:
val rainbowImage = ImageBitmap.imageResource(id = R.drawable.rainbow) val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) val customPainter = remember { OverlayImagePainter(dogImage, rainbowImage) } Image( painter = customPainter, contentDescription = stringResource(id = R.string.dog_content_description), contentScale = ContentScale.Crop, modifier = Modifier.wrapContentSize() )
A saída da combinação das duas imagens com um painter personalizado pode ser vista abaixo:
Um painter personalizado também pode ser usado com o Modifier.paint(customPainter)
para desenhar o conteúdo em um elemento combinável da seguinte maneira:
val rainbowImage = ImageBitmap.imageResource(id = R.drawable.rainbow) val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) val customPainter = remember { OverlayImagePainter(dogImage, rainbowImage) } Box( modifier = Modifier.background(color = Color.Gray) .padding(30.dp) .background(color = Color.Yellow) .paint(customPainter) ) { /** intentionally empty **/ }
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- ImageBitmap x ImageVector {:#bitmap-vs-vector}
- Gráficos no Compose
- Como carregar imagens {:#loading-images}