Viele Apps müssen in der Lage sein, genau zu steuern, was auf dem Bildschirm gezeichnet wird. Dies kann so klein sein wie die Platzierung eines Kästchens oder eines Kreises auf dem Bildschirm an der richtigen Stelle oder eine komplexe Anordnung von Grafikelementen in vielen verschiedenen Stilen.
Einfache Zeichnung mit Modifikatoren und DrawScope
Benutzerdefinierten Text lassen sich in „Compose“ hauptsächlich mit Modifizierern zeichnen, z. B. Modifier.drawWithContent
, Modifier.drawBehind
und Modifier.drawWithCache
.
Wenn Sie beispielsweise etwas aus der zusammensetzbaren Funktion zeichnen möchten, können Sie den drawBehind
-Modifikator verwenden, um mit der Ausführung von Zeichenbefehlen zu beginnen:
Spacer( modifier = Modifier .fillMaxSize() .drawBehind { // this = DrawScope } )
Wenn Sie nur eine zusammensetzbare Funktion benötigen, die etwas zeichnet, können Sie die zusammensetzbare Funktion Canvas
verwenden. Die zusammensetzbare Funktion Canvas
ist ein praktischer Wrapper um Modifier.drawBehind
. Platzieren Sie das Canvas
-Objekt in Ihrem Layout genauso wie andere Compose-UI-Elemente. In Canvas
können Sie Elemente zeichnen und dabei ihren Stil und ihre Position genau steuern.
Alle Zeichenmodifikatoren stellen ein DrawScope
bereit. Dies ist eine auf einen Bereich reduzierte Zeichenumgebung, die einen eigenen Status behält. So können Sie die Parameter für eine Gruppe grafischer Elemente festlegen. Das DrawScope
bietet mehrere nützliche Felder, z. B. size
, ein Size
-Objekt, das die aktuellen Dimensionen von DrawScope
festlegt.
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 ) }
![Rosa Rechteck, gezeichnet auf einem weißen Hintergrund, der ein Viertel des Bildschirms einnimmt](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_draw_rect.png?authuser=3&hl=de)
Weitere Informationen zu verschiedenen Zeichenmodifikatoren finden Sie in der Dokumentation zu Grafikmodifikatoren.
Koordinatensystem
Wenn Sie etwas auf dem Bildschirm zeichnen möchten, müssen Sie den Versatz (x
und y
) und die Größe des Elements kennen. Bei vielen der Zeichenmethoden für DrawScope
werden die Position und Größe durch Standardparameterwerte bereitgestellt. Die Standardparameter positionieren das Element im Allgemeinen am Punkt [0, 0]
des Canvas und stellen einen Standard-size
bereit, der den gesamten Zeichenbereich ausfüllt (siehe Beispiel oben). Das Rechteck befindet sich oben links. Um die Größe und Position eines Elements anzupassen, müssen Sie das Koordinatensystem in Compose verstehen.
Der Ursprung des Koordinatensystems ([0,0]
) befindet sich im Zeichenbereich am oberen linken Rand des Pixels. x
erhöht sich, wenn er nach rechts bewegt wird, und y
steigt, wenn er nach unten bewegt wird.
![Ein Raster mit dem Koordinatensystem oben links [0, 0] und unten rechts [Breite, Höhe].](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_coordinate_system_drawing.png?authuser=3&hl=de)
Wenn Sie beispielsweise eine diagonale Linie von der oberen rechten Ecke des Canvas-Bereichs bis zur linken unteren Ecke zeichnen 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 Sie ändern können, wo oder wie die Zeichenbefehle ausgeführt werden.
Skalieren
Mit DrawScope.scale()
können Sie die Größe Ihrer Zeichenvorgänge um einen Faktor erhöhen. Vorgänge wie scale()
gelten für alle Zeichenvorgänge innerhalb der entsprechenden Lambda-Funktion. Mit dem folgenden Code werden scaleX
beispielsweise um das 10-Fache und scaleY
um das 15-Fache erhöht:
Canvas(modifier = Modifier.fillMaxSize()) { scale(scaleX = 10f, scaleY = 15f) { drawCircle(Color.Blue, radius = 20.dp.toPx()) } }
![Ein ungleichförmig skalierter Kreis](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_scale.png?authuser=3&hl=de)
Übersetzen
Mit DrawScope.translate()
können Sie Ihre Zeichenvorgänge nach oben, unten, links oder rechts verschieben. Durch den 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()) } }
![Ein Kreis, der aus der Mitte verschoben wurde](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_translate.png?authuser=3&hl=de)
Drehen
Mit DrawScope.rotate()
können Sie Ihre Zeichenvorgänge um einen Drehpunkt drehen. Mit dem folgenden Code wird beispielsweise 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 ) } }
![Ein Smartphone mit einem um 45 Grad gedrehten Rechteck in der Mitte des Displays](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_rotate.png?authuser=3&hl=de)
rotate()
, um eine Drehung auf den aktuellen Zeichenbereich anzuwenden, wodurch das Rechteck um 45 Grad gedreht wird.
Einsatz
Mit DrawScope.inset()
können Sie die Standardparameter des aktuellen DrawScope
anpassen, indem Sie die Begrenzungen der Zeichnung ändern und die Zeichnungen entsprechend übersetzen:
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:
![Ein Rechteck mit rundem Abstand.](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_inset.png?authuser=3&hl=de)
Mehrere Transformationen
Wenn Sie mehrere Transformationen auf Ihre Zeichnungen anwenden möchten, verwenden Sie die Funktion DrawScope.withTransform()
. Diese erstellt und wendet eine einzelne Transformation an, die alle gewünschten Änderungen kombiniert. Die Verwendung von withTransform()
ist effizienter als verschachtelte Aufrufe einzelner Transformationen, da alle Transformationen gemeinsam in einem einzigen Vorgang ausgeführt werden, anstatt dass Compose jede der verschachtelten Transformationen berechnen und speichern muss.
Mit dem folgenden Code werden beispielsweise sowohl eine Übersetzung als auch eine Drehung auf das Rechteck angewendet:
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 ) } }
![Ein Smartphone mit einem gedrehten Rechteck, das auf die Seite des Displays verschoben wurde](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_multiple_transforms.png?authuser=3&hl=de)
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 und mit Anpassungen zeichnen möchten, können Sie die Methode DrawScope.drawText()
verwenden.
Um Text zu zeichnen, erstellen Sie mit rememberTextMeasurer
ein TextMeasurer
und rufen Sie drawText
mit dem Measurer auf:
val textMeasurer = rememberTextMeasurer() Canvas(modifier = Modifier.fillMaxSize()) { drawText(textMeasurer, "Hello") }
![Auf Canvas gezeichnete Hallo](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_draw_text.png?authuser=3&hl=de)
Text messen
Das Zeichnen von Text unterscheidet sich etwas von anderen Zeichenbefehlen. Normalerweise geben Sie dem Zeichenbefehl die Größe (Breite und Höhe) zum Zeichnen der Form/des Bilds an. Bei Text gibt es einige Parameter, die die Größe des gerenderten Textes steuern, z. B. Schriftgröße, Schriftart, Ligaturen und Buchstabenabstand.
Mit der Funktion „Schreiben“ können Sie einen TextMeasurer
verwenden, um abhängig von den oben genannten Faktoren Zugriff auf die gemessene Textgröße zu erhalten. Wenn Sie einen Hintergrund hinter dem Text 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:
![Mehrzeiliger Text, der 2⁄3 der gesamten Fläche einnimmt, mit einem Hintergrundrechteck](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_text_measured.png?authuser=3&hl=de)
Wenn Sie die Einschränkungen, die Schriftgröße oder andere Eigenschaften anpassen, die sich auf die gemessene Größe auswirken, wird eine neue Größe im Bericht angezeigt. Sie können sowohl für width
als auch für height
eine feste Größe festlegen. Der Text folgt dann dem festgelegten TextOverflow
. Mit dem folgenden Code wird beispielsweise Text in 1⁄3 der Höhe und 1⁄3 der Breite des zusammensetzbaren Bereichs gerendert und TextOverflow
auf TextOverflow.Ellipsis
gesetzt:
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 in den Einschränkungen mit Auslassungspunkten am Ende gezeichnet:
![Auf rosafarbenem Hintergrund gezeichneter Text mit Auslassungspunkten, die den Text abgeschnitten haben.](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_text_ellipsis.png?authuser=3&hl=de)
TextOverflow.Ellipsis
mit festen Einschränkungen bei der Textmessung.Bild zeichnen
Um ein ImageBitmap
mit DrawScope
zu zeichnen, 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) })
![Ein auf Canvas gezeichnetes Bild eines Hundes](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_image.png?authuser=3&hl=de)
ImageBitmap
auf Canvas zeichnenGrundformen zeichnen
In DrawScope
gibt es viele Funktionen zum Zeichnen von Formen. Verwenden Sie zum Zeichnen einer Form eine der vordefinierten Zeichenfunktionen wie drawCircle
:
val purpleColor = Color(0xFFBA68C8) Canvas( modifier = Modifier .fillMaxSize() .padding(16.dp), onDraw = { drawCircle(purpleColor) } )
API |
Ausgang |
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
Pfad zeichnen
Ein Pfad ist eine Reihe mathematischer Anweisungen, die nach der Ausführung zu einer Zeichnung führen. 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() )
![Ein auf dem Kopf stehendes lilafarbenes Dreieck mit dem Pfad „Schreiben“](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_path.png?authuser=3&hl=de)
Path
in Compose wird erstellt und gezeichnet.Auf Canvas
-Objekt zugreifen
Mit DrawScope
haben Sie keinen direkten Zugriff auf ein Canvas
-Objekt. Mit DrawScope.drawIntoCanvas()
erhalten Sie Zugriff auf das Canvas
-Objekt selbst, für das Sie Funktionen aufrufen können.
Wenn Sie beispielsweise ein benutzerdefiniertes Drawable
auf den Canvas zeichnen möchten, können Sie auf den Canvas zugreifen, Drawable#draw()
aufrufen und das Objekt Canvas
ü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() )
![Ein ovales schwarzes ShapeDrawable, das die gesamte Größe einnimmt](https://developer.android.com/static/develop/ui/compose/images/graphics/introduction/compose_graphics_canvas_draw_into_canvas.png?authuser=3&hl=de)
Drawable
zu zeichnen.Weitere Informationen
Weitere Informationen zum Zeichnen in Compose finden Sie in den folgenden Ressourcen:
- Grafikmodifikatoren – Informationen zu den verschiedenen Arten von Zeichenmodifikatoren
- Pinsel: Hier erfährst du, wie du die Darstellung deiner Inhalte anpassen kannst.
- Benutzerdefinierte Layouts und Grafiken in Compose – Android Dev Summit 2022: Hier erfährst du, wie du eine benutzerdefinierte UI in „Compose with Layouts and Graphics“ erstellst.
- JetLagged-Beispiel – Beispiel verfassen, das zeigt, wie ein benutzerdefiniertes Diagramm gezeichnet wird.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafikmodifikatoren
- Grafiken in „Compose“
- Ausrichtungslinien in Jetpack Compose