Zusätzlich zu den zusammensetzbaren Funktionen für Canvas
bietet „Compose“ einige nützliche Grafiken
Modifiers
, die beim Zeichnen benutzerdefinierter Inhalte helfen. Diese Modifikatoren sind nützlich,
da sie auf jede zusammensetzbare Funktion angewendet werden können.
Zeichenmodifikatoren
Alle Zeichenbefehle werden mit einem Zeichenmodifikator in Compose ausgeführt. Es gibt drei Hauptmodifikatoren für Zeichnungen in Compose:
Der Basismodifikator für das Zeichnen ist drawWithContent
. Hier können Sie festlegen,
der zusammensetzbaren Zeichen
und der Zeichenbefehle, die im
Modifikator. drawBehind
ist ein praktischer Wrapper um drawWithContent
,
die Zeichenreihenfolge hinter dem Inhalt der zusammensetzbaren Funktion. drawWithCache
ruft entweder onDrawBehind
oder onDrawWithContent
darin auf und stellt eine
zum Zwischenspeichern der darin erstellten Objekte.
Modifier.drawWithContent
: Zeichnungsreihenfolge auswählen
Mit Modifier.drawWithContent
können Sie
DrawScope
-Vorgänge vor oder nach dem Inhalt der
zusammensetzbar sind. Rufen Sie unbedingt drawContent
auf, damit der eigentliche Inhalt
der zusammensetzbaren Funktion. Mit diesem Modifikator können Sie die Reihenfolge von Operationen festlegen, wenn
Sie möchten, dass der Inhalt vor oder nach der benutzerdefinierten Zeichnung eingezeichnet wird.
Geschäftsabläufe.
Wenn Sie beispielsweise einen radialen Farbverlauf über Ihren Inhalten einen Keyhole-Effekt für die Taschenlampe in der Benutzeroberfläche erzeugen möchten, können Sie so vorgehen:
var pointerOffset by remember { mutableStateOf(Offset(0f, 0f)) } Column( modifier = Modifier .fillMaxSize() .pointerInput("dragging") { detectDragGestures { change, dragAmount -> pointerOffset += dragAmount } } .onSizeChanged { pointerOffset = Offset(it.width / 2f, it.height / 2f) } .drawWithContent { drawContent() // draws a fully black area with a small keyhole at pointerOffset that’ll show part of the UI. drawRect( Brush.radialGradient( listOf(Color.Transparent, Color.Black), center = pointerOffset, radius = 100.dp.toPx(), ) ) } ) { // Your composables here }
Modifier.drawBehind
: Zeichnung hinter einer zusammensetzbaren Funktion
Mit Modifier.drawBehind
können Sie
DrawScope
-Vorgänge hinter den zusammensetzbaren Inhalten, die auf dem Bildschirm gezeichnet werden. Wenn
Wenn Sie sich die Implementierung von Canvas
ansehen, stellen Sie möglicherweise fest,
ist nur ein praktischer Wrapper um Modifier.drawBehind
.
So zeichnen Sie ein abgerundetes Rechteck hinter Text
:
Text( "Hello Compose!", modifier = Modifier .drawBehind { drawRoundRect( Color(0xFFBBAAEE), cornerRadius = CornerRadius(10.dp.toPx()) ) } .padding(4.dp) )
Das führt zu folgendem Ergebnis:
<ph type="x-smartling-placeholder">![Text und ein mit Modifier.drawBehind gezeichneter Hintergrund](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_draw_behind.png?authuser=9&hl=de)
Modifier.drawWithCache
: Zeichenobjekte zeichnen und im Cache speichern
Modifier.drawWithCache
behält die Objekte bei
die im Cache erstellt wurden. Die Objekte werden im Cache gespeichert,
oder Statusobjekte, die gelesen werden,
geändert. Dieser Modifikator ist nützlich, um die Leistung von Zeichenaufrufen zu verbessern,
Dadurch müssen Objekte nicht neu zugewiesen werden (z. B. Brush, Shader, Path
).
die durch Zeichnen erstellt wurden.
Alternativ können Sie Objekte auch mithilfe von remember
außerhalb des
Modifikator. Dies ist jedoch nicht immer möglich, da Sie nicht immer Zugriff haben
auf die Komposition. drawWithCache
kann leistungsfähiger sein, wenn die
-Objekte werden nur zum Zeichnen verwendet.
Wenn Sie beispielsweise ein Brush
erstellen, um einen Farbverlauf hinter einem Text
zu zeichnen, verwenden Sie
drawWithCache
speichert das Brush
-Objekt im Cache, bis die Größe des Zeichenbereichs erreicht ist
Änderungen:
Text( "Hello Compose!", modifier = Modifier .drawWithCache { val brush = Brush.linearGradient( listOf( Color(0xFF9E82F0), Color(0xFF42A5F5) ) ) onDrawBehind { drawRoundRect( brush, cornerRadius = CornerRadius(10.dp.toPx()) ) } } )
![Brush-Objekt mitdrawWithCache im Cache speichern](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_draw_with_cache.png?authuser=9&hl=de)
Grafikmodifikatoren
Modifier.graphicsLayer
: Transformationen auf zusammensetzbare Funktionen anwenden
Modifier.graphicsLayer
ist ein Modifikator, der den Inhalt der zusammensetzbaren Zeichnung in eine Zeichenebene verwandelt. A
bietet die Ebene verschiedene Funktionen, z. B.:
- Isolation für die zugehörigen Zeichenanweisungen (ähnlich
RenderNode
). Zeichnen als Teil einer Ebene erfasste Anweisungen können effizient vom Rendering-Pipeline aus, ohne den Anwendungscode noch einmal auszuführen. - Transformationen, die für alle Zeichenanweisungen in einem Ebene.
- Rasterung für Kompositionsfunktionen. Wenn eine Ebene gerastert wird, Die Zeichenanweisungen werden ausgeführt und die Ausgabe wird außerhalb des Bildschirms festgehalten. Puffer. Das Compositing eines solchen Zwischenspeichers für nachfolgende Frames erfolgt schneller als Ausführen der einzelnen Anweisungen, verhält sich jedoch wie eine Bitmap, Transformationen wie Skalierung oder Rotation werden angewendet.
Transformation
Modifier.graphicsLayer
isoliert die Zeichenanweisungen. für
können verschiedene Transformationen mit Modifier.graphicsLayer
angewendet werden.
Diese können animiert oder geändert werden, ohne dass die Zeichnung erneut ausgeführt werden muss.
Lambda.
Modifier.graphicsLayer
hat keinen Einfluss auf die gemessene Größe oder Position des Geräts
zusammensetzbar, da es sich nur auf die Zeichenphase auswirkt. Das bedeutet, dass Ihre zusammensetzbare Funktion
können andere überlappen, wenn sie außerhalb der Layoutgrenzen gezeichnet wird.
Die folgenden Transformationen können mit diesem Modifikator angewendet werden:
Skalieren – Größe erhöhen
Mit scaleX
und scaleY
wird der Inhalt horizontal oder vertikal vergrößert oder verkleinert.
Richtung. Der Wert 1.0f
gibt an, dass die Skalierung nicht geändert wurde,
0.5f
steht für die Hälfte der Dimension.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.scaleX = 1.2f this.scaleY = 0.8f } )
Übersetzung
translationX
und translationY
können mit graphicsLayer
geändert werden,
translationX
verschiebt die zusammensetzbare Funktion nach links oder rechts. translationY
verschiebt den
die zusammensetzbar sind.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.translationX = 100.dp.toPx() this.translationY = 10.dp.toPx() } )
Ausrichtung
Stellen Sie rotationX
für eine horizontale Drehung, rotationY
für eine vertikale Drehung und
Mit rotationZ
können Sie sie um die Z-Achse drehen (Standardrotation). Dieser Wert ist angegeben
in Grad (0–360) angegeben.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
Origin
Ein transformOrigin
kann angegeben werden. Er wird dann als der Punkt verwendet, von dem aus
finden Transformationen statt. Bei allen bisherigen Beispielen wurde
TransformOrigin.Center
, Ort: (0.5f, 0.5f)
. Wenn Sie den Ursprung
(0f, 0f)
beginnen, beginnen die Transformationen dann links oben im
zusammensetzbar sind.
Wenn Sie den Ursprung mit einer rotationZ
-Transformation ändern, sehen Sie,
wird oben links in der zusammensetzbaren Funktion gedreht:
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.transformOrigin = TransformOrigin(0f, 0f) this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
Clip und Form
Die Form gibt den Umriss an, an dem der Inhalt abgeschnitten wird, wenn clip = true
. In
In diesem Beispiel haben wir zwei Felder mit zwei verschiedenen Clips eingerichtet:
graphicsLayer
-Variable für Clips und die andere mit dem praktischen Wrapper
Modifier.clip
.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .size(200.dp) .graphicsLayer { clip = true shape = CircleShape } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(CircleShape) .background(Color(0xFF4DB6AC)) ) }
Der Inhalt des ersten Feldes (der Text „Hello Compose“) wird auf der Kreisform:
<ph type="x-smartling-placeholder">![Clip auf zusammensetzbare Box in Box angewendet](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied.png?authuser=9&hl=de)
Wenn Sie dann ein translationY
auf den oberen rosa Kreis anwenden, sehen Sie, dass die Grenzen
der zusammensetzbaren Elemente sind immer noch dieselben, aber der Kreis wird unter dem unteren Rand
Kreis (und außerhalb der Grenzen) liegt.
![Der Clip wurde mit der Übersetzung Y und dem roten Rahmen als Umriss angewendet.](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied_red_border.png?authuser=9&hl=de)
Um die zusammensetzbare Funktion auf den dargestellten Bereich zu beschneiden, können Sie eine weitere
Modifier.clip(RectangleShape)
am Anfang der Modifikatorkette. Inhalt
bleibt innerhalb der ursprünglichen Grenzen.
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .clip(RectangleShape) .size(200.dp) .border(2.dp, Color.Black) .graphicsLayer { clip = true shape = CircleShape translationY = 50.dp.toPx() } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(RoundedCornerShape(500.dp)) .background(Color(0xFF4DB6AC)) ) }
![Clip wird auf „graphicLayer“-Transformation angewendet](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied_everything.png?authuser=9&hl=de)
Alpha
Mit Modifier.graphicsLayer
kann eine alpha
(Opazität) für das Gesamtbild festgelegt werden.
Ebene. 1.0f
ist vollständig deckend und 0.0f
nicht sichtbar.
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "clock", modifier = Modifier .graphicsLayer { this.alpha = 0.5f } )
![Bild mit angewendetem Alphatest](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/image_alpha.png?authuser=9&hl=de)
Compositing-Strategie
Die Arbeit mit Alpha und Transparenz ist möglicherweise nicht so einfach wie das Ändern eines
Alphawert. Neben dem Ändern eines Alpha-Werts gibt es auch die Option, eine
CompositingStrategy
auf graphicsLayer
. Ein CompositingStrategy
bestimmt, wie die
Inhalt der zusammensetzbaren Funktion mit den anderen
die bereits auf dem Bildschirm zu sehen sind.
Die verschiedenen Strategien sind:
Automatisch (Standard)
Die Compositing-Strategie wird durch den Rest der graphicsLayer
bestimmt.
Parameter. Er rendert die Ebene in einen Offscreen-Zwischenspeicher, wenn Alpha kleiner als ist.
1.0f oder ein RenderEffect
ist festgelegt. Immer wenn der Alphawert kleiner als 1f ist, wird ein
Compositing-Ebene wird automatisch erstellt, um den Inhalt zu rendern, und
mit dem entsprechenden Alpha-Track
an das Ziel übergeben. Festlegen eines
Durch RenderEffect
oder Overscroll werden Inhalte immer außerhalb des Bildschirms gerendert
Puffer unabhängig vom festgelegten CompositingStrategy
fest.
Nicht sichtbar
Der Inhalt der zusammensetzbaren Funktion wird immer außerhalb des Bildschirms gerastert.
Textur oder Bitmap vor dem Rendern im Ziel. Dies ist nützlich für
Anwenden von BlendMode
-Vorgängen zum Maskieren von Inhalten und für die Leistung, wenn
komplexe Reihen von Zeichenanweisungen gerendert.
Ein Beispiel für die Verwendung von CompositingStrategy.Offscreen
ist BlendModes
. Sehen wir uns das Beispiel unten an.
Sie möchten Teile einer zusammensetzbaren Image
-Funktion entfernen, indem Sie einen Draw-Befehl ausführen,
verwendet BlendMode.Clear
. Wenn Sie compositingStrategy
nicht auf
CompositingStrategy.Offscreen
, interagiert der BlendMode
mit allen Inhalten
darunter.
Image(painter = painterResource(id = R.drawable.dog), contentDescription = "Dog", contentScale = ContentScale.Crop, modifier = Modifier .size(120.dp) .aspectRatio(1f) .background( Brush.linearGradient( listOf( Color(0xFFC5E1A5), Color(0xFF80DEEA) ) ) ) .padding(8.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .drawWithCache { val path = Path() path.addOval( Rect( topLeft = Offset.Zero, bottomRight = Offset(size.width, size.height) ) ) onDrawWithContent { clipPath(path) { // this draws the actual image - if you don't call drawContent, it wont // render anything this@onDrawWithContent.drawContent() } val dotSize = size.width / 8f // Clip a white border for the content drawCircle( Color.Black, radius = dotSize, center = Offset( x = size.width - dotSize, y = size.height - dotSize ), blendMode = BlendMode.Clear ) // draw the red circle indication drawCircle( Color(0xFFEF5350), radius = dotSize * 0.8f, center = Offset( x = size.width - dotSize, y = size.height - dotSize ) ) } } )
Wenn du „CompositingStrategy
“ auf Offscreen
setzt, wird ein Out-of-Screen erstellt,
Textur, auf die die Befehle ausgeführt werden sollen. Dabei wird BlendMode
nur auf die
Inhalt dieser zusammensetzbaren Funktion). Dann wird sie auf Basis des bereits vorhandenen
ohne Auswirkungen auf den bereits gezeichneten Inhalt zu haben.
![Modifier.drawWithContent auf einem Bild mit einem Kreissymbol, mit der Option "BlendMode.Clear" in der App](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/complex_modifier_example_drawWithCache_background.png?authuser=9&hl=de)
Wenn Sie CompositingStrategy.Offscreen
nicht verwendet haben,
BlendMode.Clear
löscht alle Pixel im Ziel, unabhängig davon,
wurde bereits festgelegt, sodass der Rendering-Zwischenspeicher (schwarz) des Fensters sichtbar blieb. Viele von
BlendModes
, die Alpha beinhalten, funktionieren ohne eine
aus. Achten Sie auf den schwarzen Ring um den roten Kreis:
![Modifier.drawWithContent auf einem Bild mit einem Kreissymbol, mit dem Modus BlendMode.Clear und ohne CompositingStrategy](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/blendmode_without_compositing_strategy.png?authuser=9&hl=de)
Zum besseren Verständnis: Hat die App ein durchscheinendes Fenster?
Hintergrund und Sie haben CompositingStrategy.Offscreen
nicht verwendet, die
BlendMode
würde mit der gesamten App interagieren. Es werden alle Pixel gelöscht,
darunter die App oder den Hintergrund, wie in diesem Beispiel:
![Keine CompositingStrategy festgelegt und BlendMode.Clear wird mit einer App mit einem durchscheinenden Fensterhintergrund verwendet. Der rosa Hintergrund wird durch den Bereich um den roten Statuskreis herum angezeigt.](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/compositing_strategy_punch_through_to_wallpaper.png?authuser=9&hl=de)
Beachten Sie, dass bei der Verwendung von CompositingStrategy.Offscreen
ein nicht auf dem Bildschirm
Textur, die die Größe des Zeichenbereichs hat, wird erstellt und auf dem
Bildschirm. Alle Zeichenbefehle, die mit dieser Strategie ausgeführt werden, sind standardmäßig
auf diesen Bereich zugeschnitten. Das folgende Code-Snippet veranschaulicht die Unterschiede beim
zur Verwendung von Texturen außerhalb des sichtbaren Bereichs:
@Composable fun CompositingStrategyExamples() { Column( modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) { /** Does not clip content even with a graphics layer usage here. By default, graphicsLayer does not allocate + rasterize content into a separate layer but instead is used for isolation. That is draw invalidations made outside of this graphicsLayer will not re-record the drawing instructions in this composable as they have not changed **/ Canvas( modifier = Modifier .graphicsLayer() .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { // ... and drawing a size of 200 dp here outside the bounds drawRect(color = Color.Magenta, size = Size(200.dp.toPx(), 200.dp.toPx())) } Spacer(modifier = Modifier.size(300.dp)) /** Clips content as alpha usage here creates an offscreen buffer to rasterize content into first then draws to the original destination **/ Canvas( modifier = Modifier // force to an offscreen buffer .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { /** ... and drawing a size of 200 dp. However, because of the CompositingStrategy.Offscreen usage above, the content gets clipped **/ drawRect(color = Color.Red, size = Size(200.dp.toPx(), 200.dp.toPx())) } } }
![CompositingStrategy.Auto vs CompositingStrategy.Offscreen - Aus dem Bildschirm wird die Region abgeschnitten, in der dies nicht der Fall ist.](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/graphics_compositing_strategy.png?authuser=9&hl=de)
ModulateAlpha
Diese Kompositionsstrategie moduliert den Alpha-Track für jede der
Anweisungen, die in graphicsLayer
aufgezeichnet wurden. Es wird kein
für Alpha-Phase unter 1,0f, es sei denn, RenderEffect
ist festgelegt,
effizienter beim Alpha-Rendering. Sie kann jedoch zu anderen Ergebnissen führen,
für sich überschneidende Inhalte. Für Anwendungsfälle, bei denen im Voraus bekannt ist,
nicht überlappen, kann dies eine bessere Leistung erzielen als
CompositingStrategy.Auto
mit Alphawerten unter 1.
Ein weiteres Beispiel für verschiedene
Kompositionsstrategien finden Sie unten.
Alphas auf verschiedene Teile der zusammensetzbaren Funktionen anwenden und eine Modulate
Strategie:
@Preview @Composable fun CompositingStratgey_ModulateAlpha() { Column( modifier = Modifier .fillMaxSize() .padding(32.dp) ) { // Base drawing, no alpha applied Canvas( modifier = Modifier.size(200.dp) ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // Alpha 0.5f applied to whole composable Canvas(modifier = Modifier .size(200.dp) .graphicsLayer { alpha = 0.5f }) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // 0.75f alpha applied to each draw call when using ModulateAlpha Canvas(modifier = Modifier .size(200.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.ModulateAlpha alpha = 0.75f }) { drawSquares() } } } private fun DrawScope.drawSquares() { val size = Size(100.dp.toPx(), 100.dp.toPx()) drawRect(color = Red, size = size) drawRect( color = Purple, size = size, topLeft = Offset(size.width / 4f, size.height / 4f) ) drawRect( color = Yellow, size = size, topLeft = Offset(size.width / 4f * 2f, size.height / 4f * 2f) ) } val Purple = Color(0xFF7E57C2) val Yellow = Color(0xFFFFCA28) val Red = Color(0xFFEF5350)
![ModulateAlpha wendet den Alpha-Satz auf jeden einzelnen Zeichenbefehl an](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modulate_alpha.png?authuser=9&hl=de)
Inhalte einer zusammensetzbaren Funktion in eine Bitmap schreiben
Ein häufiger Anwendungsfall ist das Erstellen einer Bitmap
aus einer zusammensetzbaren Funktion. Zum Kopieren der
zu Bitmap
erstellen Sie ein GraphicsLayer
mit
rememberGraphicsLayer()
Leiten Sie die Zeichenbefehle mit drawWithContent()
an die neue Ebene um und
graphicsLayer.record{}
. Zeichnen Sie dann die Ebene mit
drawLayer
:
val coroutineScope = rememberCoroutineScope() val graphicsLayer = rememberGraphicsLayer() Box( modifier = Modifier .drawWithContent { // call record to capture the content in the graphics layer graphicsLayer.record { // draw the contents of the composable into the graphics layer this@drawWithContent.drawContent() } // draw the graphics layer on the visible canvas drawLayer(graphicsLayer) } .clickable { coroutineScope.launch { val bitmap = graphicsLayer.toImageBitmap() // do something with the newly acquired bitmap } } .background(Color.White) ) { Text("Hello Android", fontSize = 26.sp) }
Du kannst die Bitmap auf der Festplatte speichern und teilen. Weitere Informationen finden Sie in der vollständigen Beispiel-Snippet. Prüfe die Geräteberechtigungen, bevor du es versuchst zum Speichern auf der Festplatte.
Benutzerdefinierter Zeichnungsmodifikator
Implementieren Sie die DrawModifier
-Schnittstelle, um einen eigenen benutzerdefinierten Modifizierer zu erstellen. Dieses
bietet Ihnen Zugriff auf ein ContentDrawScope
. Dies ist dasselbe wie das gefährdete Objekt.
wenn Sie Modifier.drawWithContent()
verwenden. Sie können dann gängige Zeichnungen
zu benutzerdefinierten Zeichenmodifikatoren hinzu, um den Code zu bereinigen
praktische Wrapper; Modifier.background()
ist zum Beispiel eine praktische
DrawModifier
.
Wenn Sie z. B. eine Modifier
implementieren möchten, die den
können Sie wie folgt einen erstellen:
class FlippedModifier : DrawModifier { override fun ContentDrawScope.draw() { scale(1f, -1f) { this@draw.drawContent() } } } fun Modifier.flipped() = this.then(FlippedModifier())
Verwenden Sie dann diesen umgedrehten Modifikator auf Text
:
Text( "Hello Compose!", modifier = Modifier .flipped() )
![Benutzerdefinierter umgedrehter Modifizierer für Text](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_flipped.png?authuser=9&hl=de)
Weitere Informationen
Weitere Beispiele für die Verwendung von graphicsLayer
und benutzerdefinierten Zeichnungen finden Sie in der
folgenden Ressourcen:
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafiken in „Compose“
- Bild {:#customize-image}
- Kotlin für Jetpack Compose