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, 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ół.
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 jak
scale() 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()
, aby obracać rysunek 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 rysunku i odpowiednio przesuwają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
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 obiekt 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 – informacje 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