Symbol Brush
w funkcji tworzenia wiadomości opisuje, jak coś jest narysowane na ekranie:
określa kolory, które są rysowane w obszarze rysowania (tzn. koło,
kwadrat czy ś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ć z: Modifier.background()
, TextStyle
oraz
DrawScope
rysuj wywołania, aby zastosować styl malowania do treści.
rysowanie.
Na przykład za pomocą pędzla do rysowania poziomego gradientu można rysować koło
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 Aplikacja chce utworzyć gradient.
Lista dostępnych pędzli gradientu i odpowiadające im dane wyjściowe:
Typ pędzla gradientu | Wyjście |
---|---|
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ą funkcji 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ć określona jako ułamek,
pomiędzy 0 a 1. Jeśli ustawisz wartość większą niż 1, 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 przy podanym przesunięciu, zgodnie z definicją w tabeli colorStop
.
mniej żółty niż czerwony i niebieski.
Powtórz wzór za pomocą funkcji TileMode
Każdy gradientowy pędzel ma opcję 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.
Ten kod 4 razy powtórzy wzorzec gradientu, ponieważ endX
to
ma wartość 50.dp
, a rozmiar jest ustawiony na 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 ) ) )
W tej tabeli znajdziesz szczegółowe informacje o tym, jak różne tryby kafelka działają w przypadku
Przykład powyżej HorizontalGradient
:
TileMode | Wyjście |
---|---|
TileMode.Repeated : krawędź jest powtarzana od ostatniego do pierwszego koloru. |
|
TileMode.Mirror : odbicie lustrzane krawędzi od ostatniego koloru do pierwszego. |
|
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.
Zmień rozmiar pędzla
Jeśli znasz rozmiar obszaru, w którym będzie rysowany pędzel, możesz
ustaw kafelek endX
w taki sposób, jak pokazaliśmy 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 będzie zajmować
pełne granice gradientu DrawScope
i domyślne ustawienia środka gradientu promieniowego
do środka 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)) ) ) )
Po zmianie gradientu promieniowego w celu ustawienia promienia na maksymalny wymiar, uzyskasz lepszy efekt gradientu promieniowego:
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 zauważyć, że rzeczywisty rozmiar przekazywany przy tworzeniu
Moduł cieniujący jest określany na podstawie miejsca wywołania. Domyślnie Brush
będzie
zmienić przydział elementu Shader
wewnętrznie, jeśli rozmiar różni się od ostatniego
elementu Brush
lub jeśli obiekt stanu używany do tworzenia cieniowania został
została zmieniona.
Ten kod tworzy cieniowanie trzy razy z różnymi wartościami wraz ze zmianą rozmiaru obszaru 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 jest stosowany do kilku różnych typów rysunków: tła, tekstu i płótna. Zwrócony wynik:
Zwróć uwagę, że tekst jest teraz renderowany za pomocą ImageBitmap
, aby wypełnić piksele tekstu.
Przykład zaawansowany: niestandardowy pędzel
Szczoteczka AGSL RuntimeShader
AGSL udostępnia podzbiór funkcji Shadera GLSL. Ścianki napisane w języku migowym i używane za pomocą pędzla w funkcji Compose.
Aby utworzyć pędzel do cieniowania, najpierw zdefiniuj ciąg Shader jako ciąg AGSL do cieniowania:
@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 do cieni i ustaw uniformy dla urządzenia resolution
– jego rozmiaru
obszaru rysowania oraz elementów color
i color2
, których chcesz użyć jako danych wejściowych
Twój niestandardowy gradient:
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) ) }
Gdy go uruchomisz, na ekranie zobaczysz taki fragment kodu:
Warto pamiętać, że shadery mogą służyć do innych celów niż tylko do tworzenia gradientów, ponieważ są to obliczenia oparte na matematyce. Więcej informacji o amerykańskim języku migowym znajdziesz w Dokumentacja AGSL.
Dodatkowe materiały
Więcej przykładów użycia pędzla w funkcji tworzenia wiadomości znajdziesz w tych materiałach:
- Animowanie koloru pędzla w funkcji Compose 🖌️
- 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
- Styl tekstu