Un Brush
in Composizione descrive come viene disegnato qualcosa sullo schermo: determina i colori che vengono disegnati nell'area di disegno (ad es. un cerchio, un quadrato, un percorso). Esistono alcuni pennelli integrati utili per disegnare, come LinearGradient
, RadialGradient
o un semplice pennello SolidColor
.
I pennelli possono essere utilizzati con le chiamate di disegno Modifier.background()
, TextStyle
o DrawScope
per applicare lo stile di pittura ai contenuti in fase di disegno.
Ad esempio, un pennello con sfumatura orizzontale può essere applicato al disegno di un cerchio in
DrawScope
:
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) Canvas( modifier = Modifier.size(200.dp), onDraw = { drawCircle(brush) } )

Pennelli sfumati
Esistono molti pennelli sfumati integrati che possono essere utilizzati per ottenere diversi effetti sfumati. Questi pennelli ti consentono di specificare l'elenco dei colori da cui vuoi creare una sfumatura.
Un elenco dei pennelli sfumati disponibili e del relativo output:
Tipo di pennello sfumato | Output |
---|---|
Brush.horizontalGradient(colorList) |
![]() |
Brush.linearGradient(colorList) |
![]() |
Brush.verticalGradient(colorList) |
![]() |
Brush.sweepGradient(colorList)
Nota: per ottenere una transizione fluida tra i colori, imposta l'ultimo colore sul colore iniziale. |
![]() |
Brush.radialGradient(colorList) |
![]() |
Modifica la distribuzione dei colori con colorStops
Per personalizzare la modalità di visualizzazione dei colori nel gradiente, puoi modificare il valore
colorStops
per ciascuno. colorStops
deve essere specificato come frazione,
compresa tra 0 e 1. I valori superiori a 1 impediscono il rendering di questi colori
come parte del gradiente.
Puoi configurare le interruzioni di colore in modo che abbiano quantità diverse, ad esempio meno o più di un colore:
val colorStops = arrayOf( 0.0f to Color.Yellow, 0.2f to Color.Red, 1f to Color.Blue ) Box( modifier = Modifier .requiredSize(200.dp) .background(Brush.horizontalGradient(colorStops = colorStops)) )
I colori sono dispersi all'offset fornito come definito nella coppia colorStop
, meno giallo di rosso e blu.

Ripeti un pattern con TileMode
Ogni pennello sfumato ha la possibilità di impostare un TileMode
. Potresti non
notare TileMode
se non hai impostato un inizio e una fine per il gradiente, in quanto
riempirà l'intera area per impostazione predefinita. Un TileMode
ripete il gradiente
solo se le dimensioni dell'area sono maggiori delle dimensioni del pennello.
Il seguente codice ripeterà il pattern del gradiente 4 volte, poiché endX
è
impostato su 50.dp
e la dimensione è impostata su 200.dp
:
val listColors = listOf(Color.Yellow, Color.Red, Color.Blue) val tileSize = with(LocalDensity.current) { 50.dp.toPx() } Box( modifier = Modifier .requiredSize(200.dp) .background( Brush.horizontalGradient( listColors, endX = tileSize, tileMode = TileMode.Repeated ) ) )
Ecco una tabella che descrive in dettaglio cosa fanno le diverse modalità di riquadro per l'esempio HorizontalGradient
riportato sopra:
TileMode | Output |
---|---|
TileMode.Repeated : il bordo viene ripetuto dall'ultimo colore al primo. |
![]() |
TileMode.Mirror : il bordo viene specchiato dall'ultimo colore al primo. |
![]() |
TileMode.Clamp : il bordo è bloccato sul colore finale. Dopodiché, verrà applicato il colore più simile per il resto della regione. |
![]() |
TileMode.Decal : esegui il rendering solo fino alle dimensioni dei limiti. TileMode.Decal utilizza il nero trasparente per campionare i contenuti al di fuori dei limiti originali, mentre TileMode.Clamp campiona il colore del bordo. |
![]() |
TileMode
funziona in modo simile per gli altri gradienti direzionali, l'unica differenza è la direzione in cui si verifica la ripetizione.
Modificare le dimensioni del pennello
Se conosci le dimensioni dell'area in cui verrà disegnato il pennello, puoi
impostare il riquadro endX
come abbiamo visto sopra nella sezione TileMode
. Se ti trovi in
un DrawScope
, puoi utilizzare la proprietà size
per ottenere le dimensioni dell'area.
Se non conosci le dimensioni dell'area di disegno (ad esempio se
Brush
è assegnato a Testo), puoi estendere Shader
e utilizzare le dimensioni
dell'area di disegno nella funzione createShader
.
In questo esempio, dividi la dimensione per 4 per ripetere il pattern 4 volte:
val listColors = listOf(Color.Yellow, Color.Red, Color.Blue) val customBrush = remember { object : ShaderBrush() { override fun createShader(size: Size): Shader { return LinearGradientShader( colors = listColors, from = Offset.Zero, to = Offset(size.width / 4f, 0f), tileMode = TileMode.Mirror ) } } } Box( modifier = Modifier .requiredSize(200.dp) .background(customBrush) )

Puoi anche modificare le dimensioni del pennello di qualsiasi altra sfumatura, ad esempio le sfumature radiali. Se non specifichi una dimensione e un centro, il gradiente occuperà
l'intero riquadro di DrawScope
e il centro del gradiente radiale sarà
il centro del riquadro di DrawScope
. In questo modo, il centro del gradiente radiale
appare come il centro della dimensione più piccola (larghezza o
altezza):
Box( modifier = Modifier .fillMaxSize() .background( Brush.radialGradient( listOf(Color(0xFF2be4dc), Color(0xFF243484)) ) ) )

Quando la sfumatura radiale viene modificata per impostare le dimensioni del raggio sulla dimensione massima, puoi notare che produce un effetto di sfumatura radiale migliore:
val largeRadialGradient = object : ShaderBrush() { override fun createShader(size: Size): Shader { val biggerDimension = maxOf(size.height, size.width) return RadialGradientShader( colors = listOf(Color(0xFF2be4dc), Color(0xFF243484)), center = size.center, radius = biggerDimension / 2f, colorStops = listOf(0f, 0.95f) ) } } Box( modifier = Modifier .fillMaxSize() .background(largeRadialGradient) )

È importante notare che le dimensioni effettive passate alla creazione dello
shader sono determinate dal punto in cui viene richiamato. Per impostazione predefinita, Brush
riallocherà internamente Shader
se le dimensioni sono diverse dall'ultima creazione di Brush
o se un oggetto stato utilizzato per la creazione dello shader è cambiato.
Il seguente codice crea lo shader tre volte con dimensioni diverse man mano che le dimensioni dell'area di disegno cambiano:
val colorStops = arrayOf( 0.0f to Color.Yellow, 0.2f to Color.Red, 1f to Color.Blue ) val brush = Brush.horizontalGradient(colorStops = colorStops) Box( modifier = Modifier .requiredSize(200.dp) .drawBehind { drawRect(brush = brush) // will allocate a shader to occupy the 200 x 200 dp drawing area inset(10f) { /* Will allocate a shader to occupy the 180 x 180 dp drawing area as the inset scope reduces the drawing area by 10 pixels on the left, top, right, bottom sides */ drawRect(brush = brush) inset(5f) { /* will allocate a shader to occupy the 170 x 170 dp drawing area as the inset scope reduces the drawing area by 5 pixels on the left, top, right, bottom sides */ drawRect(brush = brush) } } } )
Utilizzare un'immagine come pennello
Per utilizzare un ImageBitmap come Brush
, carica l'immagine come ImageBitmap
e crea un pennello ImageShader
:
val imageBrush = ShaderBrush(ImageShader(ImageBitmap.imageResource(id = R.drawable.dog))) // Use ImageShader Brush with background Box( modifier = Modifier .requiredSize(200.dp) .background(imageBrush) ) // Use ImageShader Brush with TextStyle Text( text = "Hello Android!", style = TextStyle( brush = imageBrush, fontWeight = FontWeight.ExtraBold, fontSize = 36.sp ) ) // Use ImageShader Brush with DrawScope#drawCircle() Canvas(onDraw = { drawCircle(imageBrush) }, modifier = Modifier.size(200.dp))
Il pennello viene applicato a diversi tipi di disegno: uno sfondo, il testo e la tela. Viene restituito il seguente output:

Tieni presente che ora il testo viene visualizzato anche utilizzando ImageBitmap
per colorare i
pixel del testo.
Esempio avanzato: pennello personalizzato
Pennello AGSL RuntimeShader
AGSL offre un sottoinsieme delle funzionalità degli shader GLSL. Gli shader possono essere scritti in AGSL e utilizzati con un pennello in Composizione.
Per creare un pennello Shader, definisci innanzitutto lo shader come stringa di shader AGSL:
@Language("AGSL") val CUSTOM_SHADER = """ uniform float2 resolution; layout(color) uniform half4 color; layout(color) uniform half4 color2; half4 main(in float2 fragCoord) { float2 uv = fragCoord/resolution.xy; float mixValue = distance(uv, vec2(0, 1)); return mix(color, color2, mixValue); } """.trimIndent()
Lo shader precedente prende due colori di input, calcola la distanza dall'angolo in basso a sinistra (vec2(0, 1)
) dell'area di disegno ed esegue un mix
tra i due colori in base alla distanza. In questo modo viene prodotto un effetto sfumato.
Quindi, crea il pennello Shader e imposta le uniformi per resolution
, ovvero le dimensioni
dell'area di disegno, e color
e color2
che vuoi utilizzare come input per
il gradiente personalizzato:
val Coral = Color(0xFFF3A397) val LightYellow = Color(0xFFF8EE94) @RequiresApi(Build.VERSION_CODES.TIRAMISU) @Composable @Preview fun ShaderBrushExample() { Box( modifier = Modifier .drawWithCache { val shader = RuntimeShader(CUSTOM_SHADER) val shaderBrush = ShaderBrush(shader) shader.setFloatUniform("resolution", size.width, size.height) onDrawBehind { shader.setColorUniform( "color", android.graphics.Color.valueOf( LightYellow.red, LightYellow.green, LightYellow .blue, LightYellow.alpha ) ) shader.setColorUniform( "color2", android.graphics.Color.valueOf( Coral.red, Coral.green, Coral.blue, Coral.alpha ) ) drawRect(shaderBrush) } } .fillMaxWidth() .height(200.dp) ) }
Se esegui questo comando, sullo schermo viene visualizzato quanto segue:

È importante notare che con gli shader puoi fare molto di più che semplici sfumature, in quanto si tratta di calcoli matematici. Per saperne di più su AGSL, consulta la documentazione di AGSL.
Risorse aggiuntive
Per altri esempi di utilizzo di Pennello in Crea, consulta le seguenti risorse:
- Animare la colorazione del testo con il pennello in Crea 🖌️
- Custom Graphics and Layouts in Compose - Android Dev Summit 2022
- JetLagged Sample - RuntimeShader Brush
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Modificatori di grafica
- Grafica in Composizione
- Style text