Element Brush
w sekcji „Utwórz” określa, jak coś jest rysowane na ekranie: określa kolory rysowane w obszarze rysowania (np. koło, kwadrat, ścieżka). Jest kilka wbudowanych pędzli, które przydają się do rysowania.
na przykład LinearGradient
, RadialGradient
lub zwykły
pędzel SolidColor
.
Pędzli można używać w połączeniu z metodami rysowania Modifier.background()
, TextStyle
lub DrawScope
, aby zastosować styl rysunku do rysowanej treści.
Na przykład pędzel z poziomym gradientem można zastosować do narysowania koła:DrawScope
val brush = Brush.horizontalGradient(listOf(Color.Red, Color.Blue)) Canvas( modifier = Modifier.size(200.dp), onDraw = { drawCircle(brush) } )

Pędzle gradientowe
Dostępnych jest wiele wbudowanych pędzli gradientów, które można wykorzystać do uzyskania różnych efektów gradientu. Te pędzle umożliwiają określenie listy kolorów, z których ma powstać gradient.
Lista dostępnych pędzli gradientu i ich odpowiednich wyników:
Typ pędzla gradientowego | Urządzenie wyjściowe |
---|---|
Brush.horizontalGradient(colorList) |
![]() |
Brush.linearGradient(colorList) |
![]() |
Brush.verticalGradient(colorList) |
![]() |
Brush.sweepGradient(colorList)
Uwaga: aby uzyskać płynne przejście między kolorami, ustaw ostatni kolor jako kolor początkowy. |
![]() |
Brush.radialGradient(colorList) |
![]() |
Zmień rozkład kolorów za pomocą colorStops
Aby dostosować sposób wyświetlania kolorów w gradientach, możesz zmienić wartość parametru colorStops
dla każdego z nich. Wartość colorStops
powinna być podana jako ułamek w zakresie od 0 do 1. Wartości większe niż 1 spowodują, że kolory nie będą renderowane.
jako część gradientu.
Możesz skonfigurować liczbę stopni, aby różniły się wielkością, np. mniejsze lub więcej z jednego koloru:
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)) )
Kolory są rozproszone z użyciem podanego przesunięcia, jak to określono w parze colorStop
, mniej żółte niż czerwone i niebieskie.

Powtarzanie wzoru za pomocą TileMode
Każdy pędzel gradientowy ma opcję ustawienia TileMode
. Nie możesz
zwróć uwagę na TileMode
, jeśli nie ustawiono początku i końca gradientu.
domyślnie wypełnia on cały obszar. TileMode
będzie stosować gradient tylko wtedy, gdy rozmiar obszaru jest większy niż rozmiar pędzla.
Poniższy kod powtórzy wzór gradientu 4 razy, ponieważ endX
ma wartość 50.dp
, a rozmiar ma wartość 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 ) ) )
Oto tabela, która szczegółowo opisuje, jak działają różne tryby kafelków w przypadku powyższego przykładu:
Tryb kafelka | Urządzenie wyjściowe |
---|---|
TileMode.Repeated : krawędź jest powtarzana od ostatniego do pierwszego koloru. |
![]() |
TileMode.Mirror : krawędź jest lustrzanym odbiciem ostatniego koloru na pierwszy. |
![]() |
TileMode.Clamp : krawędzie są przycinane do ostatecznego koloru. Reszta obszaru zostanie pomalowana na najbliższy kolor. |
![]() |
TileMode.Decal : renderuj tylko do rozmiaru granic. W modelu TileMode.Decal użyto przezroczystej czerni do próbkowania treści poza pierwotnymi granicami, a TileMode.Clamp – kolor krawędzi. |
![]() |
Funkcja TileMode
działa w podobny sposób w przypadku innych gradientów kierunkowych, z tą różnicą, że powtórzenie występuje w innym kierunku.
Zmiana rozmiaru pędzla
Jeśli znasz rozmiar obszaru, na którym ma działać pędzel, możesz ustawić płytkę endX
tak, jak pokazano powyżej w sekcji TileMode
. Jeśli jesteś w
w tabeli DrawScope
, możesz użyć jej właściwości size
, by określić wielkość obszaru.
Jeśli nie znasz rozmiaru obszaru rysowania (na przykład, jeśli
Brush
jest przypisany do tekstu), możesz rozszerzyć zakres Shader
i wykorzystać rozmiar
obszar rysowania w funkcji createShader
.
W tym przykładzie podziel rozmiar przez 4, aby powtórzyć wzór 4 razy:
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) )

Możesz też zmienić rozmiar pędzla dowolnego innego gradientu, na przykład promieniowego.
gradientów. Jeśli nie określisz rozmiaru i środka, gradient zajmie pełne granice elementu DrawScope
, a środek gradientu promienistego będzie domyślnie ustawiony na środek granic DrawScope
. W efekcie środek gradientu promieniowego będzie znajdować się w środku mniejszego wymiaru (szerokości lub wysokości):
Box( modifier = Modifier .fillMaxSize() .background( Brush.radialGradient( listOf(Color(0xFF2be4dc), Color(0xFF243484)) ) ) )

Gdy gradient promieniowy zostanie zmieniony tak, aby rozmiar promienia odpowiadał maksymalnej wartości wymiaru, zobaczysz, że daje on lepszy efekt:
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) )

Warto pamiętać, że rzeczywisty rozmiar przekazywany do tworzenia shadera jest określany na podstawie miejsca, w którym jest wywoływany. Domyślnie Brush
przydzieli wewnętrznie Shader
, jeśli rozmiar jest inny niż podczas ostatniego utworzenia Brush
lub jeśli obiekt stanu użyty do utworzenia shadera uległ zmianie.
Podany niżej kod tworzy shader 3 razy w różnych rozmiarach, gdy zmienia się obszar rysowania:
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) } } } )
Używanie obrazu jako pędzla
Aby użyć ImageBitmap jako Brush
, wczytaj obraz jako ImageBitmap
,
i utwórz pędzel 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))
Pędzel można stosować do kilku różnych rodzajów rysowania: tła, i Canvas. Wynik:

Zwróć uwagę, że tekst jest teraz renderowany za pomocą ImageBitmap
, aby wypełnić piksele tekstu.
Przykład zaawansowany: pędzel niestandardowy
Szczoteczka AGSL RuntimeShader
AGSL udostępnia podzbiór funkcji Shadera GLSL. Programiści mogą pisać shadery w języku AGSL i używać ich z pędzlem w Compose.
Aby utworzyć pędzel Shader, najpierw zdefiniuj shader jako ciąg znaków shadera 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()
Powyższy cieniowanie przyjmuje 2 kolory wejściowe, oblicza odległość od dołu
po lewej (vec2(0, 1)
) obszaru rysowania i wykonuje mix
między dwoma kolorami
na podstawie odległości. Powoduje to efekt gradientu.
Następnie utwórz pędzel Shader i ustaw wartości uniformów dla resolution
– rozmiaru obszaru rysunku oraz color
i color2
, które chcesz użyć jako dane wejściowe do gradientu niestandardowego:
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) ) }
Po uruchomieniu zobaczysz na ekranie następujące elementy:

Warto zauważyć, że z cieniowaniem można zrobić znacznie więcej niż tylko za pomocą gradientów. Wszystkie obliczenia są oparte na matematyce. Więcej informacji o AGSL znajdziesz w dokumentacji dotyczącej tego tematu.
Dodatkowe materiały
Więcej przykładów korzystania z narzędzia Pędzel w usłudze Compose znajdziesz w tych materiałach:
- Animowanie kolorowania tekstu za pomocą pędzla w sekcji Tworzenie 🖌️
- Niestandardowe grafiki i układy w Compose – Android Dev Summit 2022
- JetLagged Sample – RuntimeShader Brush
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Modyfikatory grafiki
- Grafika w Compose
- Tekst stylizowany