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
Jest wiele wbudowanych pędzli gradientowych, za pomocą których można tworzyć Efekty 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 gradientowego | Wyjście |
---|---|
Brush.horizontalGradient(colorList) |
|
Brush.linearGradient(colorList) |
|
Brush.verticalGradient(colorList) |
|
Brush.sweepGradient(colorList)
Uwaga: aby uzyskać płynne przejście między kolorami, jako ostatni ustaw kolor początkowy. |
|
Brush.radialGradient(colorList) |
Zmień rozkład kolorów za pomocą funkcji colorStops
Aby dostosować sposób wyświetlania kolorów w gradientie, dostosowuj
Wartość każdej kolumny to colorStops
. 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 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. Element TileMode
będzie wyświetlać kafelki tylko z gradientem
jeśli 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
:
Tryb kafelka | 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ędź jest przycięta 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 podobnie w przypadku innych gradientów kierunkowych –
jest to kierunek, w którym następuje powtórzenie.
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 wyniku tego gradient promieniowy jest
jako środek mniejszego wymiaru (szerokości lub
wysokość):
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 można stosować do kilku różnych rodzajów rysowania: tła, i Canvas. Zwrócony wynik:
Zwróć uwagę, że tekst jest teraz również renderowany za pomocą komponentu ImageBitmap
do malowania
pikseli dla 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. Daje 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 kod:
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 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
- Przykład JetLagged – RuntimeShader Brush
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Modyfikatory graficzne
- Grafika w funkcji tworzenia wiadomości
- Styl tekstu