In Compose, un oggetto Painter
viene utilizzato per rappresentare qualcosa che può essere disegnato
(un sostituto delle API Drawable
definite in Android) e influenzare
la misurazione e il layout del composable corrispondente che lo utilizza . Un
BitmapPainter
acquisisce un ImageBitmap
che può disegnare un Bitmap
sullo schermo.
Per la maggior parte dei casi d'uso, l'utilizzo di painterResource()
sopra restituisce il pittore corretto per l'asset (ovvero BitmapPainter
o VectorPainter
). Per ulteriori informazioni sulle differenze tra i due, leggi la sezione ImageBitmap e ImageVector.
Un Painter
è diverso da un DrawModifier
, che disegna rigorosamente all'interno dei limiti che gli vengono assegnati e non ha alcuna influenza sulla misurazione o sul layout del componente componibile.
Per creare un pittore personalizzato, estendi la classe Painter
e implementa il metodo onDraw
, che consente l'accesso a DrawScope
per disegnare grafica personalizzata. Puoi anche eseguire l'override di intrinsicSize
, che verrà utilizzato per
influenzare il composable in cui è contenuto:
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 } }
Ora che abbiamo il nostro Painter
personalizzato, possiamo sovrapporre qualsiasi immagine a quella di origine nel seguente modo:
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() )
Di seguito è riportato l'output della combinazione delle due immagini con un pittore personalizzato:

È possibile utilizzare un pittore personalizzato anche con Modifier.paint(customPainter)
per disegnare i contenuti in un elemento componibile come segue:
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 **/ }
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- ImageBitmap vs ImageVector {:#bitmap-vs-vector}
- Grafica in Composizione
- Caricamento delle immagini {:#loading-images}