Grafikmodifikatoren

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. 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
}

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 1: Modifier.drawWithContent wird auf einem Composable verwendet, um eine Benutzeroberfläche vom Typ "Taschenlampe" zu erstellen.

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">
</ph> Text und ein mit Modifier.drawBehind gezeichneter Hintergrund
Abbildung 2: Mit Modifier.drawBehind gezeichneter Text und ein Hintergrund

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())
                )
            }
        }
)

<ph type="x-smartling-placeholder">
</ph> Brush-Objekt mitdrawWithCache im Cache speichern
Abbildung 3: Brush-Objekt mitdrawWithCache im Cache speichern

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
        }
)

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 4: scaleX und scaleY auf eine zusammensetzbare Funktion des Bildes angewendet
Ü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()
        }
)

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 5: TranslationX und TranslationY mit Modifier.graphicsLayer auf das Bild angewendet
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
        }
)

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 6: RotationX, RotationY und RotationZ werden durch Modifier.graphicsLayer für das Bild festgelegt
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.

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
        }
)

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 7: Rotation angewendet, wobei TransformOrigin auf 0f, 0f gesetzt ist

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">
</ph> Clip auf zusammensetzbare Box in Box angewendet
Abbildung 8: Clip auf zusammensetzbare Box angewendet

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.

<ph type="x-smartling-placeholder">
</ph> Der Clip wurde mit der Übersetzung Y und dem roten Rahmen als Umriss angewendet.
Abbildung 9: Clip mit Übersetzung Y angewendet und roter Rahmen für Umriss

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))
    )
}

<ph type="x-smartling-placeholder">
</ph> Clip wird auf „graphicLayer“-Transformation angewendet
Abbildung 10: Clip wird auf „graphicLayer“-Transformation angewendet

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
        }
)

<ph type="x-smartling-placeholder">
</ph> Bild mit angewendetem Alphatest
Abbildung 11: Bild mit angewendetem Alpha-Test

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.

<ph type="x-smartling-placeholder">
</ph> Modifier.drawWithContent auf einem Bild mit einem Kreissymbol, mit der Option &quot;BlendMode.Clear&quot; in der App
Abbildung 12: Modifier.drawWithContent auf einem Bild mit einem Kreissymbol mit den Optionen BlendMode.Clear und CompositingStrategy.Offscreen in der App

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:

<ph type="x-smartling-placeholder">
</ph> Modifier.drawWithContent auf einem Bild mit einem Kreissymbol, mit dem Modus BlendMode.Clear und ohne CompositingStrategy
Abbildung 13: Modifier.drawWithContent auf einem Bild mit einem Kreissymbol, mit dem Modus BlendMode.Clear und ohne CompositingStrategy

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:

<ph type="x-smartling-placeholder">
</ph> 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.
Abbildung 14: Keine CompositingStrategy festgelegt und Verwendung von BlendMode.Clear bei einer App mit durchscheinendem Fensterhintergrund. Beachten Sie, wie der rosa Hintergrund um den roten Statuskreis herum angezeigt wird.

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()))
       }
   }
}

<ph type="x-smartling-placeholder">
</ph> CompositingStrategy.Auto vs CompositingStrategy.Offscreen - Aus dem Bildschirm wird die Region abgeschnitten, in der dies nicht der Fall ist.
Abbildung 15: CompositingStrategy.Auto vs. CompositingStrategy.Offscreen – Offscreen-Video wird an die Region angepasst, in der dies nicht der Fall ist.
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)

<ph type="x-smartling-placeholder">
</ph> ModulateAlpha wendet den Alpha-Satz auf jeden einzelnen Zeichenbefehl an
Abbildung 16: ModulateAlpha wendet das Alpha-Dataset auf jeden einzelnen Zeichenbefehl an.

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()
)

<ph type="x-smartling-placeholder">
</ph> Benutzerdefinierter umgedrehter Modifizierer für Text
Abbildung 17: Benutzerdefinierter umgedrehter Modifizierer für Text

Weitere Informationen

Weitere Beispiele für die Verwendung von graphicsLayer und benutzerdefinierten Zeichnungen finden Sie in der folgenden Ressourcen: