Wiele aplikacji musi mieć możliwość precyzyjnego kontrolowania tego, co jest wyświetlane na ekranie. Może to być coś tak prostego jak umieszczenie pola lub okręgu na ekranie w odpowiednim miejscu albo skomplikowany układ elementów graficznych w wielu różnych stylach.
Podstawowy rysunek z modyfikatorami i DrawScope
Podstawowym sposobem rysowania niestandardowych elementów w Compose są modyfikatory, takie jak Modifier.drawWithContent, Modifier.drawBehind i Modifier.drawWithCache.
Jeśli na przykład chcesz 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 funkcji kompozycyjnej, która rysuje, możesz użyć funkcji kompozycyjnej Canvas. Funkcja kompozycyjna Canvas to wygodna otoka wokół Modifier.drawBehind. Element Canvas umieszczasz w układzie tak samo jak każdy inny element interfejsu Compose. W Canvas możesz rysować elementy, precyzyjnie kontrolując ich styl i lokalizację.
Wszystkie modyfikatory rysowania udostępniają DrawScope, czyli ograniczone środowisko rysowania, które zachowuje własny stan. Umożliwia to ustawienie parametrów dla grupy elementów graficznych. DrawScope zawiera kilka przydatnych pól, takich jak size, obiekt Size określający bieżące wymiary DrawScope.
Aby coś narysować, możesz użyć jednej z wielu funkcji rysowania w DrawScope. Na przykład ten 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 – prostokąt znajduje się w lewym górnym rogu. Aby dostosować rozmiar i położenie elementu, musisz zrozumieć system współrzędnych w Compose.
Punkt początkowy układu współrzędnych ([0,0]) znajduje się w lewym górnym pikselu obszaru rysowania. Wartość x rośnie, gdy przesuwasz się w prawo, a wartość y rośnie, gdy przesuwasz się w dół.
Jeśli na przykład chcesz narysować linię po przekątnej od prawego górnego rogu obszaru roboczego do lewego dolnego rogu, możesz użyć funkcji DrawScope.drawLine() i określić przesunięcie początkowe i końcowe z odpowiednimi pozycjami 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 ) }
Przekształcenia podstawowe
DrawScope oferuje przekształcenia, które zmieniają miejsce lub sposób wykonywania poleceń rysowania.
Skaluj
Użyj DrawScope.scale(), aby zwiększyć rozmiar operacji rysowania o współczynnik. Operacje takie jak scale() mają zastosowanie do wszystkich operacji rysowania w odpowiedniej funkcji lambda. Na przykład ten kod zwiększa scaleX 10 razy, a scaleY 15 razy:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }
Tłumacz
Użyj przycisków DrawScope.translate(), aby przesuwać operacje rysowania w górę, w dół, w lewo lub w prawo. Na przykład ten 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ć operacje rysowania 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, co powoduje obrót prostokąta o 45 stopni.
Odcięcie
Użyj DrawScope.inset(), aby dostosować domyślne parametry bieżącego DrawScope, zmieniając granice rysunku i odpowiednio go przesuwając:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
Ten kod skutecznie dodaje dopełnienie do poleceń rysowania:
Wiele przekształceń
Aby zastosować do rysunków kilka przekształceń, użyj funkcji DrawScope.withTransform(), która tworzy i stosuje pojedyncze przekształcenie łączące wszystkie żądane 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, zamiast obliczania i zapisywania przez Compose każdego 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 użyć funkcji kompozycyjnej Text. Jeśli jednak używasz DrawScope lub chcesz ręcznie narysować tekst z dostosowaniem, możesz użyć metody DrawScope.drawText().
Aby narysować tekst, utwórz TextMeasurer za pomocą rememberTextMeasurer i wywołaj drawText z miernikiem:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }
Tekst pomiaru
Rysowanie tekstu działa nieco inaczej niż inne polecenia rysowania. Zwykle polecenie rysowania zawiera rozmiar (szerokość i wysokość), w jakim ma zostać 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, że tekst ma różowe tło:
Dostosowanie ograniczeń, rozmiaru czcionki lub dowolnej właściwości, która wpływa na mierzony rozmiar, powoduje zgłoszenie nowego rozmiaru. Możesz ustawić stały rozmiar zarówno dla width, jak i height, a tekst będzie zgodny z ustawionym TextOverflow. Na przykład ten kod renderuje tekst na ⅓ wysokości i ⅓ szerokości obszaru kompozycyjnego oraz ustawia 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.Narysuj obraz
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,
W DrawScope jest wiele funkcji rysowania kształtów. Aby narysować kształt, użyj jednej ze zdefiniowanych wstępnie funkcji rysowania, np. drawCircle:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
Interfejs API |
Wyniki |
|
|
|
|
|
|
|
|
|
|
|
|
|
Narysuj ścieżkę
Ścieżka to seria instrukcji matematycznych, które po wykonaniu dają 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(), używając 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.Uzyskiwanie dostępu do obiektu Canvas
W DrawScope nie masz bezpośredniego dostępu do obiektu Canvas. Możesz użyć DrawScope.drawIntoCanvas(), aby uzyskać dostęp do obiektu Canvas, na którym możesz wywoływać funkcje.
Jeśli na przykład masz niestandardowy obiekt Drawable, który chcesz narysować na obszarze roboczym, możesz uzyskać dostęp do obszaru roboczego i wywołać 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 utworzyć niestandardowy interfejs użytkownika w Compose za pomocą układów i grafiki.
- JetLagged Sample – przykładowa aplikacja Compose, która pokazuje, jak narysować niestandardowy wykres.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Modyfikatory grafiki
- Grafika w Compose
- Linie wyrównania w Jetpack Compose