Ein Brush
in Compose beschreibt, wie etwas auf dem Bildschirm gezeichnet wird. Es bestimmt die Farbe(n), die im Zeichenbereich (z. B. ein Kreis, ein Quadrat oder ein Pfad) gezeichnet werden. Es gibt einige integrierte Pinsel, die sich gut zum Zeichnen eignen, z. B. LinearGradient
, RadialGradient
oder ein einfacher SolidColor
-Pinsel.
Pinsel können mit Modifier.background()
-, TextStyle
- oder DrawScope
-Zeichnungsaufrufen verwendet werden, um den Malstil auf die gezeichneten Inhalte anzuwenden.
Eine horizontale Farbverlaufspinsel kann beispielsweise zum Zeichnen eines Kreises in DrawScope
verwendet werden:
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) Canvas( modifier = Modifier.size(200.dp), onDraw = { drawCircle(brush) } )

Verlaufspinsel
Es gibt viele integrierte Verlaufs-Pinsel, mit denen sich verschiedene Verlaufs-Effekte erzielen lassen. Mit diesen Pinseln können Sie die Liste der Farben angeben, aus denen Sie einen Verlauf erstellen möchten.
Eine Liste der verfügbaren Farbverlaufs-Pinsel und der entsprechenden Ausgabe:
Art der Farbverlaufspinsel | Ausgabe |
---|---|
Brush.horizontalGradient(colorList) |
![]() |
Brush.linearGradient(colorList) |
![]() |
Brush.verticalGradient(colorList) |
![]() |
Brush.sweepGradient(colorList)
Hinweis: Wenn Sie einen sanften Übergang zwischen den Farben wünschen, legen Sie die letzte Farbe auf die Startfarbe fest. |
![]() |
Brush.radialGradient(colorList) |
![]() |
Verteilung der Farben mit colorStops
ändern
Wenn Sie anpassen möchten, wie die Farben im Farbverlauf dargestellt werden, können Sie den colorStops
-Wert für jede Farbe ändern. colorStops
sollte als Bruch zwischen 0 und 1 angegeben werden. Werte über 1 führen dazu, dass diese Farben nicht als Teil des Farbverlaufs gerendert werden.
Sie können die Farbunterbrechungen so konfigurieren, dass sie unterschiedliche Mengen einer Farbe enthalten:
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)) )
Die Farben werden mit dem angegebenen Offset verteilt, wie im colorStop
-Paar definiert. Sie sind weniger gelb als rot und blau.

Muster mit TileMode
wiederholen
Für jede Verlaufs-Pinselspitze kann ein TileMode
festgelegt werden. Wenn Sie keinen Start- und Endpunkt für den Farbverlauf festgelegt haben, wird TileMode
möglicherweise nicht angezeigt, da standardmäßig der gesamte Bereich ausgefüllt wird. Ein TileMode
kachelt den Farbverlauf nur, wenn die Größe des Bereichs größer als die Pinselgröße ist.
Im folgenden Code wird das Gradientenmuster viermal wiederholt, da endX
auf 50.dp
und die Größe auf 200.dp
festgelegt ist:
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 ) ) )
In der folgenden Tabelle wird beschrieben, was die verschiedenen Kachelmodi für das Beispiel HorizontalGradient
oben bewirken:
TileMode | Ausgabe |
---|---|
TileMode.Repeated : Die Kante wird von der letzten zur ersten Farbe wiederholt. |
![]() |
TileMode.Mirror : Die Kante wird von der letzten zur ersten Farbe gespiegelt. |
![]() |
TileMode.Clamp : Die Kante wird auf die endgültige Farbe begrenzt. Anschließend wird für den Rest der Region die nächstgelegene Farbe verwendet. |
![]() |
TileMode.Decal : Nur bis zur Größe der Grenzen rendern. Bei TileMode.Decal wird transparentes Schwarz verwendet, um Inhalte außerhalb der ursprünglichen Grenzen zu erfassen, während bei TileMode.Clamp die Kantenfarbe erfasst wird. |
![]() |
TileMode
funktioniert für die anderen gerichteten Verläufe ähnlich. Der Unterschied besteht in der Richtung, in der die Wiederholung erfolgt.
Pinselgröße ändern
Wenn Sie die Größe des Bereichs kennen, in dem der Pinsel verwendet wird, können Sie die Kachel endX
wie oben im Abschnitt TileMode
beschrieben festlegen. Wenn Sie sich in einem DrawScope
befinden, können Sie die Größe des Bereichs mit der Eigenschaft size
abrufen.
Wenn Sie die Größe des Zeichenbereichs nicht kennen (z. B. wenn Brush
dem Text zugewiesen ist), können Sie Shader
erweitern und die Größe des Zeichenbereichs in der Funktion createShader
verwenden.
In diesem Beispiel wird die Größe durch 4 geteilt, um das Muster viermal zu wiederholen:
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) )

Sie können auch die Pinselgröße anderer Farbverläufe ändern, z. B. bei radialen Farbverläufen. Wenn Sie keine Größe und keinen Mittelpunkt angeben, nimmt der Farbverlauf die gesamte Begrenzung des DrawScope
ein und der Mittelpunkt des radialen Farbverlaufs wird standardmäßig auf den Mittelpunkt der DrawScope
-Begrenzung festgelegt. Dadurch wird der Mittelpunkt des radialen Verlaufs als Mittelpunkt der kleineren Dimension (entweder Breite oder Höhe) angezeigt:
Box( modifier = Modifier .fillMaxSize() .background( Brush.radialGradient( listOf(Color(0xFF2be4dc), Color(0xFF243484)) ) ) )

Wenn der radiale Farbverlauf geändert wird, um die Radiusgröße auf die maximale Dimension festzulegen, wird ein besserer radialer Farbverlaufseffekt erzielt:
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) )

Die tatsächliche Größe, die beim Erstellen des Shaders übergeben wird, hängt davon ab, wo er aufgerufen wird. Standardmäßig wird Brush
intern neu zugewiesen, wenn die Größe sich von der letzten Erstellung von Brush
unterscheidet oder wenn sich ein Statusobjekt, das bei der Erstellung des Shaders verwendet wird, geändert hat.Shader
Mit dem folgenden Code wird der Shader dreimal mit unterschiedlichen Größen erstellt, da sich die Größe des Zeichenbereichs ändert:
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) } } } )
Bild als Pinsel verwenden
Wenn Sie ein ImageBitmap als Brush
verwenden möchten, laden Sie das Bild als ImageBitmap
und erstellen Sie einen ImageShader
-Pinsel:
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))
Der Pinsel wird auf verschiedene Arten von Zeichnungen angewendet: einen Hintergrund, den Text und das Canvas. Dadurch wird Folgendes ausgegeben:

Der Text wird jetzt auch mit dem ImageBitmap
gerendert, um die Pixel für den Text zu malen.
Erweitertes Beispiel: Benutzerdefinierter Pinsel
AGSL RuntimeShader
-Pinsel
AGSL bietet eine Teilmenge der GLSL-Shaderfunktionen. Shader können in AGSL geschrieben und mit einem Pinsel in Compose verwendet werden.
Um einen Shader-Pinsel zu erstellen, definieren Sie den Shader zuerst als AGSL-Shader-String:
@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()
Der Shader oben verwendet zwei Eingabefarben, berechnet den Abstand von der unteren linken Ecke (vec2(0, 1)
) des Zeichenbereichs und führt basierend auf dem Abstand eine mix
zwischen den beiden Farben aus. Dadurch entsteht ein Farbverlauf.
Erstellen Sie dann den Shader-Pinsel und legen Sie die Uniformen für resolution
– die Größe des Zeichenbereichs – sowie für color
und color2
fest, die Sie als Eingabe für Ihren benutzerdefinierten Farbverlauf verwenden möchten:
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) ) }
Wenn Sie diesen Code ausführen, wird Folgendes auf dem Bildschirm gerendert:

Mit Shadern lässt sich viel mehr als nur Farbverläufe erstellen, da sie auf mathematischen Berechnungen basieren. Weitere Informationen zu AGSL finden Sie in der AGSL-Dokumentation.
Zusätzliche Ressourcen
Weitere Beispiele für die Verwendung von „Brush“ in Compose finden Sie in den folgenden Ressourcen:
- Pinsel-Textfarbe in Compose animieren 🖌️
- Benutzerdefinierte Grafiken und Layouts in Compose – Android Dev Summit 2022
- JetLagged Sample – RuntimeShader Brush
Empfehlungen für dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafikmodifikatoren
- Grafiken in Compose
- Text formatieren