Wiele aplikacji musi mieć możliwość precyzyjnego kontrolowania tego, co jest wyświetlane na ekranie. Może to być tak proste, jak umieszczenie na ekranie w odpowiednim miejscu pola lub okręgu, albo tak złożone, jak skomplikowany układ elementów graficznych w wielu różnych stylach.
Podstawowy rysunek z modyfikatorami i symbolem DrawScope
Podstawowym sposobem rysowania niestandardowych elementów w Compose są modyfikatory, takie jak Modifier.drawWithContent
, Modifier.drawBehind
i Modifier.drawWithCache
.
Aby na przykład narysować coś za elementem kompozycyjnym, możesz użyć modyfikatora
drawBehind
, aby rozpocząć wykonywanie poleceń rysowania:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
Jeśli potrzebujesz tylko komponentu kompozycyjnego, który rysuje, możesz użyć komponentu Canvas
. Funkcja kompozycyjna Canvas
to wygodna otoczka funkcji Modifier.drawBehind
. Element Canvas
umieszcza się w układzie tak samo jak każdy inny element interfejsu Compose. W sekcji
Canvas
możesz rysować elementy, precyzyjnie kontrolując ich styl i położenie.
Wszystkie modyfikatory rysowania udostępniają DrawScope
, czyli środowisko rysowania o określonym zakresie, które zachowuje własny stan. Umożliwia to ustawienie parametrów grupy elementów graficznych. DrawScope
udostępnia kilka przydatnych pól, np. size
, obiekt Size
określający bieżące wymiary DrawScope
.
Aby coś narysować, możesz użyć jednej z wielu funkcji rysowania na DrawScope
. Na przykład poniższy kod rysuje prostokąt w lewym górnym rogu ekranu:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }

Więcej informacji o różnych modyfikatorach rysowania znajdziesz w dokumentacji modyfikatorów grafiki.
Układ współrzędnych
Aby narysować coś na ekranie, musisz znać przesunięcie (x
i y
) oraz rozmiar elementu. W przypadku wielu metod rysowania w DrawScope
pozycja i rozmiar są podawane przez domyślne wartości parametrów. Domyślne parametry zwykle umieszczają element w punkcie [0, 0]
na obszarze roboczym i zapewniają domyślny size
, który wypełnia cały obszar rysowania, jak w przykładzie powyżej – widać, że prostokąt znajduje się w lewym górnym rogu. Aby dostosować rozmiar i położenie elementu, musisz poznać system współrzędnych w Compose.
Punkt początkowy układu współrzędnych ([0,0]
) znajduje się w lewym górnym rogu obszaru rysowania. x
rośnie w miarę przesuwania się w prawo, a y
rośnie w miarę przesuwania się w dół.
![Siatka przedstawiająca układ współrzędnych z lewym górnym rogiem [0, 0] i prawym dolnym rogiem [szerokość, wysokość].](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png?authuser=0000&hl=pl)
Jeśli np. chcesz narysować linię ukośną od prawego górnego rogu obszaru rysowania do lewego dolnego rogu, możesz użyć funkcji DrawScope.drawLine()
i określić przesunięcie początku i końca za pomocą odpowiednich pozycji x i y:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasWidth = size.width val canvasHeight = size.height drawLine( start = Offset(x = canvasWidth, y = 0f), end = Offset(x = 0f, y = canvasHeight), color = Color.Blue ) }
Podstawowe przekształcenia
DrawScope
oferuje przekształcenia, które zmieniają miejsce lub sposób wykonywania poleceń rysowania.
Skala
Użyj
DrawScope.scale()
aby zwiększyć rozmiar operacji rysowania o określony współczynnik. Operacje takie jakscale()
mają zastosowanie do wszystkich operacji rysowania w odpowiedniej funkcji lambda. Na przykład poniższy kod zwiększa wartość scaleX
10 razy, a wartość scaleY
15 razy:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }

Tłumacz
Użyj DrawScope.translate()
, aby przesuwać rysunek w górę, w dół, w lewo lub w prawo. Na przykład poniższy kod przesuwa rysunek o 100 pikseli w prawo i o 300 pikseli w górę:
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }

Obróć
Użyj
DrawScope.rotate()
do obracania rysunku wokół punktu obrotu. Na przykład ten kod obraca prostokąt o 45 stopni:
Canvas(modifier = Modifier.fillMaxSize()) { rotate(degrees = 45F) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

rotate()
, aby zastosować obrót do bieżącego zakresu rysowania, który obraca prostokąt o 45 stopni.
Wcięcie
Użyj DrawScope.inset()
, aby dostosować domyślne parametry bieżącego DrawScope
, zmieniając granice rysowania i odpowiednio przekształcając rysunki:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
Ten kod skutecznie dodaje do poleceń rysowania dopełnienie:

Wiele przekształceń
Aby zastosować do rysunków wiele przekształceń, użyj funkcji
DrawScope.withTransform()
, która tworzy i stosuje jedno przekształcenie łączące wszystkie wybrane zmiany. Używanie funkcji
withTransform()
jest bardziej wydajne niż wykonywanie zagnieżdżonych wywołań poszczególnych
przekształceń, ponieważ wszystkie przekształcenia są wykonywane razem w ramach
jednej operacji. Nie ma więc potrzeby, aby funkcja Compose obliczała i zapisywała każde z zagnieżdżonych przekształceń.
Na przykład ten kod stosuje do prostokąta zarówno przesunięcie, jak i obrót:
Canvas(modifier = Modifier.fillMaxSize()) { withTransform({ translate(left = size.width / 5F) rotate(degrees = 45F) }) { drawRect( color = Color.Gray, topLeft = Offset(x = size.width / 3F, y = size.height / 3F), size = size / 3F ) } }

withTransform
, aby zastosować zarówno obrót, jak i przesunięcie, obracając prostokąt i przesuwając go w lewo.Typowe operacje rysowania
Rysowanie tekstu
Aby narysować tekst w Compose, możesz zwykle użyć funkcji kompozycyjnej Text
. Jeśli jednak jesteś w DrawScope
lub chcesz narysować tekst ręcznie z dostosowaniem, możesz użyć metody DrawScope.drawText()
.
Aby narysować tekst, utwórz obiekt TextMeasurer
za pomocą funkcji rememberTextMeasurer
i wywołaj funkcję drawText
z użyciem narzędzia pomiarowego:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }

Mierzenie tekstu
Rysowanie tekstu działa nieco inaczej niż inne polecenia rysowania. Zwykle podajesz poleceniu rysowania rozmiar (szerokość i wysokość), w jakim ma być narysowany kształt lub obraz. W przypadku tekstu istnieje kilka parametrów, które kontrolują rozmiar renderowanego tekstu, takich jak rozmiar czcionki, czcionka, ligatury i odstępy między literami.
W Compose możesz użyć TextMeasurer
, aby uzyskać dostęp do zmierzonego rozmiaru tekstu w zależności od powyższych czynników. Jeśli chcesz narysować tło za tekstem, możesz użyć zmierzonych informacji, aby uzyskać rozmiar obszaru zajmowanego przez tekst:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()), style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
Ten fragment kodu powoduje wyświetlenie tekstu na różowym tle:

Dostosowanie ograniczeń, rozmiaru czcionki lub dowolnej właściwości, która wpływa na zmierzony rozmiar, powoduje zgłoszenie nowego rozmiaru. Możesz ustawić stały rozmiar zarówno elementu width
, jak i height
, a tekst będzie wtedy zgodny z ustawionym TextOverflow
. Na przykład poniższy kod renderuje tekst na ⅓ wysokości i ⅓ szerokości obszaru kompozycji oraz ustawia wartość TextOverflow
na TextOverflow.Ellipsis
:
val textMeasurer = rememberTextMeasurer() Spacer( modifier = Modifier .drawWithCache { val measuredText = textMeasurer.measure( AnnotatedString(longTextSample), constraints = Constraints.fixed( width = (size.width / 3f).toInt(), height = (size.height / 3f).toInt() ), overflow = TextOverflow.Ellipsis, style = TextStyle(fontSize = 18.sp) ) onDrawBehind { drawRect(pinkColor, size = measuredText.size.toSize()) drawText(measuredText) } } .fillMaxSize() )
Tekst jest teraz rysowany w ramach ograniczeń z wielokropkiem na końcu:

TextOverflow.Ellipsis
ze stałymi ograniczeniami dotyczącymi pomiaru tekstu.Rysowanie obrazu
Aby narysować ImageBitmap
za pomocą DrawScope
, wczytaj obraz za pomocą
ImageBitmap.imageResource()
, a następnie wywołaj drawImage
:
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })

ImageBitmap
w Canvas.Rysowanie podstawowych kształtów
DrawScope
ma wiele funkcji rysowania kształtów. Aby narysować kształt, użyj jednej ze wstępnie zdefiniowanych funkcji rysowania, np. drawCircle
:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
Interfejs API |
Urządzenie wyjściowe |
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
Rysowanie ścieżki
Ścieżka to seria instrukcji matematycznych, które po wykonaniu tworzą rysunek. DrawScope
może narysować ścieżkę za pomocą metody DrawScope.drawPath()
.
Załóżmy na przykład, że chcesz narysować trójkąt. Ścieżkę możesz wygenerować za pomocą funkcji takich jak lineTo()
i moveTo()
, korzystając z rozmiaru obszaru rysowania.
Następnie wywołaj funkcję drawPath()
z nowo utworzoną ścieżką, aby uzyskać trójkąt.
Spacer( modifier = Modifier .drawWithCache { val path = Path() path.moveTo(0f, 0f) path.lineTo(size.width / 2f, size.height / 2f) path.lineTo(size.width, 0f) path.close() onDrawBehind { drawPath(path, Color.Magenta, style = Stroke(width = 10f)) } } .fillMaxSize() )

Path
w Compose.Dostęp do obiektu Canvas
W przypadku DrawScope
nie masz bezpośredniego dostępu do obiektu Canvas
. Możesz użyć DrawScope.drawIntoCanvas()
, aby uzyskać dostęp do samego obiektu Canvas
, na którym możesz wywoływać funkcje.
Jeśli na przykład masz niestandardowy Drawable
, który chcesz narysować na
płótnie, możesz uzyskać dostęp do płótna i wywołać funkcję Drawable#draw()
, przekazując obiekt
Canvas
:
val drawable = ShapeDrawable(OvalShape()) Spacer( modifier = Modifier .drawWithContent { drawIntoCanvas { canvas -> drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt()) drawable.draw(canvas.nativeCanvas) } } .fillMaxSize() )

Drawable
.Więcej informacji
Więcej informacji o rysowaniu w Compose znajdziesz w tych materiałach:
- Modyfikatory grafiki – dowiedz się więcej o różnych typach modyfikatorów rysowania.
- Pędzel – dowiedz się, jak dostosować malowanie treści.
- Niestandardowe układy i grafika w Compose – Android Dev Summit 2022 – dowiedz się, jak tworzyć niestandardowy interfejs w Compose za pomocą układów i grafiki.
- JetLagged Sample – przykładowy kod, który pokazuje, jak narysować wykres niestandardowy.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Modyfikatory grafiki
- Grafika w komponowaniu
- Linie wyrównania w Jetpack Compose