Bei vielen Apps muss genau gesteuert werden können, was auf dem Bildschirm gezeichnet wird. Sie könnten zum Beispiel einen Kasten oder einen Kreis auf dem Bildschirm platzieren. oder eine aufwendige Anordnung grafischer Elemente in vielen verschiedenen Stilen.
Einfache Zeichnung mit Modifikatoren und DrawScope
Benutzerdefinierte Elemente lassen sich in „Schreiben“ hauptsächlich mit Modifikatoren zeichnen, z. B.
Modifier.drawWithContent
,
Modifier.drawBehind
und
Modifier.drawWithCache
Wenn Sie beispielsweise etwas hinter Ihrem Composeable zeichnen möchten, können Sie mit der Tastenkombination drawBehind
Zeichenbefehle ausführen:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
Wenn Sie nur ein grafisches Element benötigen, können Sie das Canvas
-Element verwenden. Das Canvas
-Komposit ist eine praktische Ummantelung für Modifier.drawBehind
. Sie platzieren das Canvas
in Ihrem Layout genauso wie jedes andere Compose-UI-Element. Im
Canvas
können Sie Elemente zeichnen und dabei ihren Stil und
Standort.
Alle Zeichenmodifikatoren stellen eine DrawScope
bereit, eine begrenzte Zeichenumgebung, die ihren eigenen Status beibehält. So können Sie die Parameter für eine Gruppe
grafische Elemente. Das DrawScope
-Objekt enthält mehrere nützliche Felder, z. B. size
, ein Size
-Objekt, das die aktuellen Dimensionen des DrawScope
angibt.
Um etwas zu zeichnen, können Sie eine der vielen Zeichenfunktionen in DrawScope
verwenden. Mit dem folgenden Code wird beispielsweise ein Rechteck in der oberen linken Ecke des Bildschirms gezeichnet:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F drawRect( color = Color.Magenta, size = canvasQuadrantSize ) }

Weitere Informationen zu verschiedenen Modifikatoren zum Zeichnen finden Sie unter Grafikmodifikatoren. Dokumentation.
Koordinatensystem
Um etwas auf dem Bildschirm zu zeichnen, müssen Sie den Versatz (x
und y
) und die Größe des
Ihren Artikel. Bei vielen der Zeichenmethoden auf DrawScope
sind die Position und Größe
werden durch Standardparameterwerte bereitgestellt. Mit den Standardparametern wird das Element in der Regel am [0, 0]
-Punkt auf dem Canvas positioniert und ein Standardsize
festgelegt, der den gesamten Zeichenbereich füllt, wie im Beispiel oben. Das Rechteck ist hier links oben zu sehen. Wenn Sie die Größe und Position eines Elements anpassen möchten, müssen Sie das Koordinatensystem in Compose kennen.
Der Ursprung des Koordinatensystems ([0,0]
) befindet sich im linken oberen Pixel des Zeichenbereichs. Der Wert von x
steigt bei Bewegung nach rechts und y
im Laufe der Zeit an.
nach unten zeigen.
![Ein Raster mit dem Koordinatensystem, das die obere linke Ecke [0, 0] und die untere rechte Ecke [Breite, Höhe] zeigt](https://developer.android.google.cn/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png?hl=de)
Wenn Sie beispielsweise eine Diagonale von der rechten oberen Ecke des Canvas-Bereichs zur linken unteren Ecke ziehen möchten, können Sie die Funktion DrawScope.drawLine()
verwenden und einen Start- und Endversatz mit den entsprechenden x- und y-Positionen angeben:
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 ) }
Grundlegende Transformationen
DrawScope
bietet Transformationen, mit denen sich ändern lässt, wo oder wie die Zeichenbefehle verwendet werden
ausgeführt werden.
Skalieren
Verwenden Sie
DrawScope.scale()
um die Größe Ihrer Zeichenvorgänge um einen Faktor zu erhöhen. Vorgänge wie
scale()
gelten für alle Zeichenvorgänge innerhalb der entsprechenden Lambda-Funktion. Im folgenden Code wird scaleX
beispielsweise zehnmal und scaleY
fünfzehnmal erhöht:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }

Übersetzen
Mit DrawScope.translate()
können Sie die Zeichnungen nach oben, unten, links oder rechts verschieben. Mit dem folgenden Code wird die Zeichnung beispielsweise um 100 Pixel nach rechts und 300 Pixel nach oben verschoben:
Canvas(modifier = Modifier.fillMaxSize()) { translate(left = 100f, top = -300f) { drawCircle(Color.Blue, radius = 200.dp.toPx()) } }

Drehen
Verwenden Sie
DrawScope.rotate()
um Ihre Zeichenvorgänge um einen Drehpunkt zu drehen. Beispiel: Der Parameter
Mit dem folgenden Code wird ein Rechteck um 45 Grad gedreht:
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()
, um eine Drehung auf den aktuellen Zeichenbereich anzuwenden, wodurch das Rechteck um 45 Grad gedreht wird.
Eingebettet
Mit DrawScope.inset()
können Sie die Standardparameter der aktuellen
DrawScope
, wobei die Grenzen der Zeichnung geändert und die Zeichnungen übersetzt werden
entsprechend:
Canvas(modifier = Modifier.fillMaxSize()) { val canvasQuadrantSize = size / 2F inset(horizontal = 50f, vertical = 30f) { drawRect(color = Color.Green, size = canvasQuadrantSize) } }
Mit diesem Code wird den Zeichenbefehlen effektiv ein Padding hinzugefügt:

Mehrere Transformationen
Um mehrere Transformationen auf Ihre Zeichnungen anzuwenden, verwenden Sie die Methode
DrawScope.withTransform()
-Funktion, die ein
wendet eine einzelne Transformation an, in der alle gewünschten Änderungen kombiniert werden. Mit
withTransform()
ist effizienter als verschachtelte Aufrufe an einzelne Nutzer.
da alle Transformationen gemeinsam in einem
anstatt Compose einzeln zu berechnen und zu speichern,
verschachtelte Transformationen ein.
Mit dem folgenden Code werden beispielsweise sowohl eine Übersetzung als auch eine Rotation auf den Rechteck:
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
können Sie sowohl eine Drehung als auch eine Verschiebung anwenden. Drehen Sie dazu das Rechteck und verschieben Sie es nach links.Gängige Zeichenvorgänge
Text zeichnen
Um Text in „Schreiben“ zu zeichnen, können Sie normalerweise die zusammensetzbare Funktion Text
verwenden. Wenn Sie sich jedoch in einem DrawScope
befinden oder den Text manuell mit Anpassungen zeichnen möchten, können Sie die Methode DrawScope.drawText()
verwenden.
Wenn Sie Text zeichnen möchten, erstellen Sie mit rememberTextMeasurer
eine TextMeasurer
und rufen Sie drawText
mit dem Messwert auf:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }

Text messen
Das Zeichnen von Text funktioniert etwas anders als andere Zeichenbefehle. Normalerweise geben Sie dem Zeichenbefehl die Größe (Breite und Höhe) an, in der die Form/das Bild gezeichnet werden soll. Bei Text gibt es einige Parameter, die die Größe des gerenderten Text, wie etwa Schriftgröße, Schriftart, Ligaturen und Buchstabenabstand.
In Compose können Sie mithilfe eines TextMeasurer
auf die gemessene Textgröße zugreifen, die von den oben genannten Faktoren abhängt. Wenn Sie hinter dem Text einen Hintergrund zeichnen möchten, können Sie anhand der gemessenen Informationen die Größe des Bereichs ermitteln, den der Text einnimmt:
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() )
Bei diesem Code-Snippet wird der Text mit einem rosa Hintergrund versehen:

Anpassen der Einschränkungen, der Schriftgröße oder anderer Eigenschaften, die sich auf die gemessene Größe auswirken
führt zu einer neuen Größe. Sie können sowohl für width
als auch für
und height
. Der Text folgt dann auf TextOverflow
. Für
Beispiel: Der folgende Code rendert Text in 1⁄3 der Höhe und 1⁄3 der Breite
des zusammensetzbaren Bereichs und legt TextOverflow
auf TextOverflow.Ellipsis
fest:
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() )
Der Text wird jetzt innerhalb der Begrenzungen mit Auslassungspunkten am Ende dargestellt:

TextOverflow.Ellipsis
mit festen Einschränkungen bei der Textmessung.Bild zeichnen
Wenn Sie mit DrawScope
ein ImageBitmap
zeichnen möchten, laden Sie das Bild mit ImageBitmap.imageResource()
und rufen Sie dann drawImage
auf:
val dogImage = ImageBitmap.imageResource(id = R.drawable.dog) Canvas(modifier = Modifier.fillMaxSize(), onDraw = { drawImage(dogImage) })

ImageBitmap
auf CanvasEinfache Formen zeichnen
In DrawScope
gibt es viele Funktionen zum Zeichnen von Formen. Verwenden Sie zum Zeichnen einer Form eine der vordefinierten Zeichenfunktionen, z. B. drawCircle
:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
API |
Ausgabe |
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
Pfad zeichnen
Ein Pfad ist eine Reihe mathematischer Anweisungen, die einmal zu einer Zeichnung führen
ausgeführt haben. DrawScope
kann mit der Methode DrawScope.drawPath()
einen Pfad zeichnen.
Angenommen, Sie möchten ein Dreieck zeichnen. Sie können einen Pfad mit Funktionen wie lineTo()
und moveTo()
anhand der Größe des Zeichenbereichs generieren.
Rufen Sie dann drawPath()
mit diesem neu erstellten Pfad auf, um ein Dreieck zu erhalten.
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
in Compose wird erstellt und gezeichnet.Zugriff auf Canvas
-Objekt
Mit DrawScope
haben Sie keinen direkten Zugriff auf ein Canvas
-Objekt. Mit DrawScope.drawIntoCanvas()
können Sie auf das Canvas
-Objekt selbst zugreifen, für das Sie Funktionen aufrufen können.
Wenn Sie beispielsweise ein benutzerdefiniertes Drawable
haben, das Sie auf dem Canvas zeichnen möchten, können Sie auf den Canvas zugreifen und Drawable#draw()
aufrufen, wobei Sie das Canvas
-Objekt übergeben:
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
zu zeichnenWeitere Informationen
Weitere Informationen zu Zeichnungen in „Compose“ finden Sie in den folgenden Ressourcen:
- Grafikmodifikatoren - Erfahren Sie mehr über die verschiedenen Zeichenarten. Modifizierern.
- Pinsel: Hier erfahren Sie, wie Sie das Malen Ihrer Inhalte anpassen.
- Benutzerdefinierte Layouts und Grafiken in Compose – Android Dev Summit 2022 – Anleitung zum Erstellen einer benutzerdefinierten UI in der Funktion „Mit Layouts erstellen“ und Grafiken.
- JetLagged Sample: Beispiel für die Erstellung eines benutzerdefinierten Diagramms.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafikmodifikatoren
- Grafiken in „Compose“
- Ausrichtungslinien in Jetpack Compose