Auf Canvas-Objekte zeichnen

Dieses Codelab ist Teil des Kurses „Advanced Android in Kotlin“. Sie können den größten Nutzen aus diesem Kurs ziehen, wenn Sie die Codelabs der Reihe nach durcharbeiten. Das ist jedoch nicht zwingend erforderlich. Alle Codelabs des Kurses sind auf der Landingpage für Codelabs zu „Android für Fortgeschrittene mit Kotlin“ aufgeführt.

Einführung

Unter Android stehen Ihnen mehrere Techniken zur Verfügung, um benutzerdefinierte 2D-Grafiken und ‑Animationen in Ansichten zu implementieren.

Neben Drawables können Sie auch 2D-Zeichnungen mit den Zeichenmethoden der Klasse Canvas erstellen. Das Canvas ist eine 2D-Zeichenfläche, die Methoden zum Zeichnen bietet. Das ist nützlich, wenn Ihre App regelmäßig neu gezeichnet werden muss, weil sich das, was der Nutzer sieht, im Laufe der Zeit ändert. In diesem Codelab erfahren Sie, wie Sie ein Canvas erstellen und darauf zeichnen, das in einem View angezeigt wird.

Folgende Arten von Vorgängen können Sie für einen Arbeitsbereich ausführen:

  • Füllen Sie die gesamte Arbeitsfläche mit Farbe.
  • Hiermit werden Formen wie Rechtecke, Bögen und Pfade gezeichnet, die gemäß einem Paint-Objekt formatiert sind. Das Paint-Objekt enthält die Stil- und Farbinformationen zum Zeichnen von Geometrien (z. B. Linien, Rechtecke, Ovale und Pfade) oder z. B. die Schriftart von Text.
  • Transformationen wie Übersetzung, Skalierung oder benutzerdefinierte Transformationen anwenden.
  • Sie können das Canvas zuschneiden, d. h. eine Form oder einen Pfad darauf anwenden, um die sichtbaren Bereiche zu definieren.

Android-Zeichnungen (sehr vereinfacht)

Das Zeichnen in Android oder einem anderen modernen System ist ein komplexer Prozess, der Abstraktionsebenen und Optimierungen bis hin zur Hardware umfasst. Wie Android zeichnet, ist ein faszinierendes Thema, über das viel geschrieben wurde. Die Details gehen über den Rahmen dieses Codelabs hinaus.

Im Kontext dieses Codelabs und seiner App, die auf einem Canvas für die Anzeige im Vollbildmodus basiert, können Sie sich das so vorstellen:

  1. Sie benötigen eine Ansicht, in der das Gezeichnete angezeigt wird. Dies kann eine der Ansichten sein, die vom Android-System bereitgestellt werden. In diesem Codelab erstellen Sie eine benutzerdefinierte Ansicht, die als Inhaltsansicht für Ihre App dient (MyCanvasView).
  2. Wie alle Ansichten hat auch diese Ansicht einen eigenen Arbeitsbereich (canvas).
  3. Wenn Sie auf dem Canvas einer Ansicht zeichnen möchten, überschreiben Sie die Methode onDraw() und zeichnen auf dem Canvas.
  4. Wenn Sie eine Zeichnung erstellen, müssen Sie das, was Sie zuvor gezeichnet haben, im Cache speichern. Es gibt verschiedene Möglichkeiten, Ihre Daten zu cachen. Eine davon ist in einem Bitmap (extraBitmap). Eine andere besteht darin, einen Verlauf der gezeichneten Elemente als Koordinaten und Anweisungen zu speichern.
  5. Wenn Sie mit der Canvas-Zeichen-API in Ihr Caching-Bitmap (extraBitmap) zeichnen möchten, erstellen Sie ein Caching-Canvas (extraCanvas) für Ihr Caching-Bitmap.
  6. Anschließend zeichnen Sie auf das Caching-Canvas (extraCanvas), wodurch auf die Caching-Bitmap (extraBitmap) gezeichnet wird.
  7. Damit alles, was auf dem Bildschirm gezeichnet wurde, angezeigt wird, weisen Sie den Canvas der Ansicht (canvas) an, die Caching-Bitmap (extraBitmap) zu zeichnen.

Was Sie bereits wissen sollten

  • So erstellen Sie eine App mit einer Aktivität und einem einfachen Layout und führen sie mit Android Studio aus.
  • So verknüpfen Sie Ereignishandler mit Ansichten.
  • Benutzerdefinierte Ansicht erstellen

Lerninhalte

  • So erstellen Sie ein Canvas und zeichnen darauf, wenn der Nutzer es berührt.

Aufgaben

  • Erstellen Sie eine App, die Linien auf dem Bildschirm zeichnet, wenn der Nutzer den Bildschirm berührt.
  • Bewegungsereignisse erfassen und als Reaktion darauf Linien auf eine Leinwand zeichnen, die auf dem Bildschirm in einer benutzerdefinierten Vollbildansicht angezeigt wird.

Die App MiniPaint verwendet eine benutzerdefinierte Ansicht, um als Reaktion auf Berührungen durch den Nutzer eine Linie zu zeichnen, wie im Screenshot unten zu sehen ist.

Schritt 1: MiniPaint-Projekt erstellen

  1. Erstellen Sie ein neues Kotlin-Projekt namens MiniPaint, das die Vorlage Empty Activity verwendet.
  2. Öffnen Sie die Datei app/res/values/colors.xml und fügen Sie die folgenden beiden Farben hinzu.
<color name="colorBackground">#FFFF5500</color>
<color name="colorPaint">#FFFFEB3B</color>
  1. styles.xml öffnen
  2. Ersetzen Sie im übergeordneten Element des angegebenen AppTheme-Stils DarkActionBar durch NoActionBar. Dadurch wird die Aktionsleiste entfernt, sodass Sie im Vollbildmodus zeichnen können.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

Schritt 2: Klasse „MyCanvasView“ erstellen

In diesem Schritt erstellen Sie eine benutzerdefinierte Ansicht, MyCanvasView, zum Zeichnen.

  1. Erstellen Sie im Paket app/java/com.example.android.minipaint eine Neue > Kotlin-Datei/Klasse mit dem Namen MyCanvasView.
  2. Lassen Sie die MyCanvasView-Klasse die View-Klasse erweitern und übergeben Sie die context: Context. Übernehmen Sie die vorgeschlagenen Importe.
import android.content.Context
import android.view.View

class MyCanvasView(context: Context) : View(context) {
}

Schritt 3: MyCanvasView als Inhaltsansicht festlegen

Damit das, was Sie in MyCanvasView zeichnen, angezeigt wird, müssen Sie es als Inhaltsansicht von MainActivity festlegen.

  1. Öffnen Sie strings.xml und definieren Sie einen String, der für die Inhaltsbeschreibung der Ansicht verwendet werden soll.
<string name="canvasContentDescription">Mini Paint is a simple line drawing app.
   Drag your fingers to draw. Rotate the phone to clear.</string>
  1. MainActivity.kt öffnen
  2. Löschen Sie in onCreate() die setContentView(R.layout.activity_main).
  3. Erstellen Sie eine Instanz von MyCanvasView.
val myCanvasView = MyCanvasView(this)
  1. Fordere darunter den Vollbildmodus für das Layout von myCanvasView an. Setzen Sie dazu das Flag SYSTEM_UI_FLAG_FULLSCREEN auf myCanvasView. So wird die Ansicht auf dem gesamten Bildschirm dargestellt.
myCanvasView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
  1. Fügen Sie eine Inhaltsbeschreibung hinzu.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
  1. Legen Sie darunter die Inhaltsansicht auf myCanvasView fest.
setContentView(myCanvasView)
  1. Führen Sie die App aus. Sie sehen einen vollständig weißen Bildschirm, da die Leinwand keine Größe hat und Sie noch nichts gezeichnet haben.

Schritt 1: onSizeChanged() überschreiben

Die Methode onSizeChanged() wird vom Android-System aufgerufen, wenn sich die Größe einer Ansicht ändert. Da die Ansicht anfangs keine Größe hat, wird die onSizeChanged()-Methode der Ansicht auch aufgerufen, nachdem die Aktivität sie erstellt und aufgeblasen hat. Diese onSizeChanged()-Methode ist daher der ideale Ort, um den Canvas der Ansicht zu erstellen und einzurichten.

  1. Definieren Sie in MyCanvasView auf Klassenebene Variablen für einen Canvas und eine Bitmap. Nennen Sie sie extraCanvas und extraBitmap. Dies sind Ihre Bitmap und Ihr Canvas zum Zwischenspeichern von zuvor gezeichneten Elementen.
private lateinit var extraCanvas: Canvas
private lateinit var extraBitmap: Bitmap
  1. Definieren Sie eine Variable auf Klassenebene backgroundColor für die Hintergrundfarbe des Canvas und initialisieren Sie sie mit dem colorBackground, das Sie zuvor definiert haben.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
  1. Überschreiben Sie in MyCanvasView die Methode onSizeChanged(). Diese Callback-Methode wird vom Android-System mit den geänderten Bildschirmabmessungen aufgerufen, d. h. mit einer neuen Breite und Höhe (für die Änderung) und der alten Breite und Höhe (von der aus die Änderung erfolgt).
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
   super.onSizeChanged(width, height, oldWidth, oldHeight)
}
  1. Erstellen Sie in onSizeChanged() eine Instanz von Bitmap mit der neuen Breite und Höhe, die der Bildschirmgröße entsprechen, und weisen Sie sie extraBitmap zu. Das dritte Argument ist die Bitmap-Farbkonfiguration. Bei ARGB_8888 wird jede Farbe in 4 Byte gespeichert. Diese Option wird empfohlen.
extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  1. Erstellen Sie eine Canvas-Instanz aus extraBitmap und weisen Sie sie extraCanvas zu.
 extraCanvas = Canvas(extraBitmap)
  1. Geben Sie die Hintergrundfarbe an, mit der extraCanvas gefüllt werden soll.
extraCanvas.drawColor(backgroundColor)
  1. In onSizeChanged() werden bei jeder Ausführung der Funktion ein neues Bitmap und ein neuer Canvas erstellt. Sie benötigen eine neue Bitmap, da sich die Größe geändert hat. Dies führt jedoch zu einem Speicherleck, da die alten Bitmaps weiterhin vorhanden sind. Um dieses Problem zu beheben, müssen Sie extraBitmap wiederverwenden, bevor Sie das nächste Element erstellen. Fügen Sie dazu diesen Code direkt nach dem Aufruf von super ein.
if (::extraBitmap.isInitialized) extraBitmap.recycle()

Schritt 2: onDraw() überschreiben

Alle Zeichenarbeiten für MyCanvasView werden in onDraw() ausgeführt.

Zeigen Sie zuerst den Canvas an und füllen Sie den Bildschirm mit der Hintergrundfarbe, die Sie in onSizeChanged() festgelegt haben.

  1. Überschreiben Sie onDraw() und zeichnen Sie den Inhalt des im Cache gespeicherten extraBitmap auf die mit der Ansicht verknüpfte Arbeitsfläche. Die Methode drawBitmap() Canvas ist in mehreren Versionen verfügbar. In diesem Code geben Sie die Bitmap, die x- und y-Koordinaten (in Pixeln) der oberen linken Ecke und null für die Paint an, da Sie diese später festlegen.
override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
canvas.drawBitmap(extraBitmap, 0f, 0f, null)
}


Beachten Sie, dass sich der Canvas, der an onDraw() übergeben und vom System zum Anzeigen der Bitmap verwendet wird, von dem Canvas unterscheidet, den Sie in der Methode onSizeChanged() erstellt und zum Zeichnen auf der Bitmap verwendet haben.

  1. Führen Sie Ihre App aus. Der gesamte Bildschirm sollte mit der angegebenen Hintergrundfarbe gefüllt sein.

Zum Zeichnen benötigen Sie ein Paint-Objekt, das angibt, wie die Elemente beim Zeichnen formatiert werden, und ein Path-Objekt, das angibt, was gezeichnet wird.

Schritt 1: Paint-Objekt initialisieren

  1. Definieren Sie in MyCanvasView.kt auf der obersten Dateiebene eine Konstante für die Strichstärke.
private const val STROKE_WIDTH = 12f // has to be float
  1. Definieren Sie auf Klassenebene von MyCanvasView eine Variable drawColor, in der die Farbe gespeichert wird, mit der gezeichnet werden soll. Initialisieren Sie sie mit der zuvor definierten colorPaint-Ressource.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
  1. Fügen Sie auf Klassenebene unten eine Variable paint für ein Paint-Objekt hinzu und initialisieren Sie sie so:
// Set up the paint with which to draw.
private val paint = Paint().apply {
   color = drawColor
   // Smooths out edges of what is drawn without affecting shape.
   isAntiAlias = true
   // Dithering affects how colors with higher-precision than the device are down-sampled.
   isDither = true
   style = Paint.Style.STROKE // default: FILL
   strokeJoin = Paint.Join.ROUND // default: MITER
   strokeCap = Paint.Cap.ROUND // default: BUTT
   strokeWidth = STROKE_WIDTH // default: Hairline-width (really thin)
}
  • Der color des paint ist der drawColor, den Sie zuvor definiert haben.
  • isAntiAlias gibt an, ob die Kantenglättung angewendet werden soll. Wenn Sie isAntiAlias auf true setzen, werden die Kanten des Gezeichneten geglättet, ohne dass sich dies auf die Form auswirkt.
  • isDither, wenn true, wirkt sich darauf aus, wie Farben mit höherer Präzision als das Gerät heruntergerechnet werden. Dithering ist beispielsweise die gängigste Methode, um den Farbbereich von Bildern auf 256 Farben (oder weniger) zu reduzieren.
  • Mit style wird der Typ der Malerei für einen Strich festgelegt, der im Wesentlichen eine Linie ist. Paint.Style gibt an, ob das gezeichnete Primitive gefüllt, mit einem Strich versehen oder beides (in derselben Farbe) ist. Standardmäßig wird das Objekt gefüllt, auf das die Farbe angewendet wird. Mit „Füllung“ wird das Innere der Form gefärbt, während „Strichstärke“ der Kontur folgt.
  • strokeJoin von Paint.Join gibt an, wie Linien und Kurvensegmente auf einem gestrichenen Pfad verbunden werden. Der Standardwert ist MITER.
  • Mit strokeCap wird die Form des Endes der Linie auf einen Abschluss festgelegt. Mit Paint.Cap wird angegeben, wie der Anfang und das Ende von gestrichelten Linien und Pfaden dargestellt werden. Der Standardwert ist BUTT.
  • strokeWidth gibt die Breite des Strichs in Pixeln an. Die Standardeinstellung ist „Haarlinie“, die sehr dünn ist. Daher wird sie auf die zuvor definierte Konstante STROKE_WIDTH gesetzt.

Schritt 2: Path-Objekt initialisieren

Die Path ist der Pfad, den der Nutzer zeichnet.

  1. Fügen Sie in MyCanvasView eine Variable path hinzu und initialisieren Sie sie mit einem Path-Objekt, um den Pfad zu speichern, der gezeichnet wird, wenn Sie der Berührung des Nutzers auf dem Bildschirm folgen. Importieren Sie android.graphics.Path für Path.
private var path = Path()

Schritt 1: Auf Bewegungen auf dem Display reagieren

Die onTouchEvent()-Methode für eine Ansicht wird immer aufgerufen, wenn der Nutzer das Display berührt.

  1. Überschreiben Sie in MyCanvasView die Methode onTouchEvent(), um die x- und y-Koordinaten des übergebenen event im Cache zu speichern. Verwenden Sie dann einen when-Ausdruck, um Bewegungsereignisse für das Aufsetzen des Fingers auf dem Display, das Bewegen des Fingers auf dem Display und das Loslassen des Fingers auf dem Display zu verarbeiten. Das sind die Ereignisse, die für das Zeichnen einer Linie auf dem Bildschirm relevant sind. Rufen Sie für jeden Ereignistyp eine Hilfsmethode auf, wie im folgenden Code gezeigt. Eine vollständige Liste der Touch-Ereignisse finden Sie in der Klassendokumentation zu MotionEvent.
override fun onTouchEvent(event: MotionEvent): Boolean {
   motionTouchEventX = event.x
   motionTouchEventY = event.y

   when (event.action) {
       MotionEvent.ACTION_DOWN -> touchStart()
       MotionEvent.ACTION_MOVE -> touchMove()
       MotionEvent.ACTION_UP -> touchUp()
   }
   return true
}
  1. Fügen Sie auf Klassenebene die fehlenden Variablen motionTouchEventX und motionTouchEventY hinzu, um die x- und y-Koordinaten des aktuellen Touch-Ereignisses (die MotionEvent-Koordinaten) im Cache zu speichern. Initialisieren Sie sie mit 0f.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
  1. Erstellen Sie Stubs für die drei Funktionen touchStart(), touchMove() und touchUp().
private fun touchStart() {}

private fun touchMove() {}

private fun touchUp() {}
  1. Ihr Code sollte kompiliert und ausgeführt werden, aber Sie sehen noch nichts anderes als den farbigen Hintergrund.

Schritt 2: touchStart() implementieren

Diese Methode wird aufgerufen, wenn der Nutzer den Bildschirm zum ersten Mal berührt.

  1. Fügen Sie auf Klassenebene Variablen hinzu, um die letzten x- und y-Werte im Cache zu speichern. Wenn der Nutzer sich nicht mehr bewegt und den Finger vom Display nimmt, sind diese Punkte der Ausgangspunkt für den nächsten Pfad (das nächste Segment der zu zeichnenden Linie).
private var currentX = 0f
private var currentY = 0f
  1. Implementieren Sie die Methode touchStart() so: Setzen Sie path zurück, wechseln Sie zu den x-y-Koordinaten des Touch-Ereignisses (motionTouchEventX und motionTouchEventY) und weisen Sie diesem Wert currentX und currentY zu.
private fun touchStart() {
   path.reset()
   path.moveTo(motionTouchEventX, motionTouchEventY)
   currentX = motionTouchEventX
   currentY = motionTouchEventY
}

Schritt 3: touchMove() implementieren

  1. Fügen Sie auf Klassenebene eine touchTolerance-Variable hinzu und legen Sie sie auf ViewConfiguration.get(context).scaledTouchSlop fest.
private val touchTolerance = ViewConfiguration.get(context).scaledTouchSlop

Wenn Sie einen Pfad verwenden, müssen Sie nicht jedes Pixel zeichnen und jedes Mal eine Aktualisierung des Displays anfordern. Stattdessen können Sie (und werden Sie) einen Pfad zwischen Punkten interpolieren, um eine viel bessere Leistung zu erzielen.

  • Wenn sich der Finger kaum bewegt hat, müssen Sie nichts zeichnen.
  • Wenn sich der Finger weniger als die touchTolerance-Distanz bewegt hat, zeichnen Sie nicht.
  • scaledTouchSlop gibt die Distanz in Pixeln zurück, die eine Berührung zurücklegen kann, bevor das System davon ausgeht, dass der Nutzer scrollt.
  1. Definieren Sie die Methode touchMove(). Berechne die zurückgelegte Distanz (dx, dy), erstelle eine Kurve zwischen den beiden Punkten und speichere sie in path, aktualisiere die laufenden currentX- und currentY-Zähler und zeichne die path. Rufen Sie dann invalidate() auf, um das erneute Zeichnen des Bildschirms mit dem aktualisierten path zu erzwingen.
private fun touchMove() {
   val dx = Math.abs(motionTouchEventX - currentX)
   val dy = Math.abs(motionTouchEventY - currentY)
   if (dx >= touchTolerance || dy >= touchTolerance) {
       // QuadTo() adds a quadratic bezier from the last point,
       // approaching control point (x1,y1), and ending at (x2,y2).
       path.quadTo(currentX, currentY, (motionTouchEventX + currentX) / 2, (motionTouchEventY + currentY) / 2)
       currentX = motionTouchEventX
       currentY = motionTouchEventY
       // Draw the path in the extra bitmap to cache it.
       extraCanvas.drawPath(path, paint)
   }
   invalidate()
}

Diese Methode im Detail:

  1. Berechne die zurückgelegte Strecke (dx, dy).
  2. Wenn die Bewegung über die Berührungstoleranz hinausging, fügen Sie dem Pfad ein Segment hinzu.
  3. Legen Sie den Startpunkt für das nächste Segment auf den Endpunkt dieses Segments fest.
  4. Wenn Sie quadTo() anstelle von lineTo() verwenden, wird eine glatte Linie ohne Ecken gezeichnet. Weitere Informationen zu Bézierkurven
  5. Rufen Sie invalidate() auf, um (eventuell onDraw() aufzurufen und) die Ansicht neu zu zeichnen.

Schritt 4: touchUp() implementieren

Wenn der Nutzer den Finger vom Display nimmt, muss der Pfad nur zurückgesetzt werden, damit er nicht noch einmal gezeichnet wird. Es wird nichts gezeichnet, daher ist keine Ungültigmachung erforderlich.

  1. Implementieren Sie die Methode touchUp().
private fun touchUp() {
   // Reset the path so it doesn't get drawn again.
   path.reset()
}
  1. Führen Sie den Code aus und zeichnen Sie mit dem Finger auf den Bildschirm. Wenn Sie das Gerät drehen, wird der Bildschirm gelöscht, da der Zeichenstatus nicht gespeichert wird. In dieser Beispiel-App ist das so gewollt, damit der Nutzer den Bildschirm einfach leeren kann.

Schritt 5: Rahmen um die Skizze zeichnen

Während der Nutzer auf dem Bildschirm zeichnet, erstellt Ihre App den Pfad und speichert ihn in der Bitmap extraBitmap. Die Methode onDraw() zeigt die zusätzliche Bitmap auf dem Canvas der Ansicht an. In onDraw() können Sie mehr zeichnen. Sie könnten beispielsweise nach dem Zeichnen der Bitmap Formen zeichnen.

In diesem Schritt zeichnen Sie einen Rahmen um den Rand des Bildes.

  1. Fügen Sie in MyCanvasView eine Variable namens frame hinzu, die ein Rect-Objekt enthält.
private lateinit var frame: Rect
  1. Definieren Sie am Ende von onSizeChanged() einen Inset und fügen Sie Code hinzu, um das Rect zu erstellen, das für den Rahmen verwendet wird. Verwenden Sie dazu die neuen Abmessungen und den Inset.
// Calculate a rectangular frame around the picture.
val inset = 40
frame = Rect(inset, inset, width - inset, height - inset)
  1. Zeichnen Sie in onDraw() nach dem Zeichnen der Bitmap ein Rechteck.
// Draw a frame around the canvas.
canvas.drawRect(frame, paint)
  1. Führen Sie die App aus. Achten Sie auf den Frame.

Aufgabe (optional): Daten in einem Pfad speichern

In der aktuellen App werden die Zeichnungsinformationen in einer Bitmap gespeichert. Das ist zwar eine gute Lösung, aber nicht die einzige Möglichkeit, Zeichnungsinformationen zu speichern. Wie Sie Ihren Zeichenverlauf speichern, hängt von der App und Ihren Anforderungen ab. Wenn Sie beispielsweise Formen zeichnen, können Sie eine Liste der Formen mit ihrer Position und ihren Abmessungen speichern. Für die MiniPaint App könnten Sie den Pfad als Path speichern. Unten finden Sie eine allgemeine Anleitung dazu, falls Sie es versuchen möchten.

  1. Entfernen Sie in MyCanvasView den gesamten Code für extraCanvas und extraBitmap.
  2. Fügen Sie Variablen für den bisherigen Pfad und den aktuell gezeichneten Pfad hinzu.
// Path representing the drawing so far
private val drawing = Path()

// Path representing what's currently being drawn
private val curPath = Path()
  1. Zeichnen Sie in onDraw() anstelle der Bitmap die gespeicherten und aktuellen Pfade.
// Draw the drawing so far
canvas.drawPath(drawing, paint)
// Draw any current squiggle
canvas.drawPath(curPath, paint)
// Draw a frame around the canvas
canvas.drawRect(frame, paint)
  1. Fügen Sie in touchUp() den aktuellen Pfad zum vorherigen Pfad hinzu und setzen Sie den aktuellen Pfad zurück.
// Add the current path to the drawing so far
drawing.addPath(curPath)
// Rewind the current path for the next touch
curPath.reset()
  1. Führen Sie Ihre App aus. Es sollte keinen Unterschied geben.

Laden Sie den Code für das fertige Codelab herunter.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-canvas


Alternativ können Sie das Repository als ZIP-Datei herunterladen, entzippen und in Android Studio öffnen.

Zip herunterladen

  • Ein Canvas ist eine 2D-Zeichenfläche, die Methoden zum Zeichnen bietet.
  • Die Canvas kann einer View-Instanz zugeordnet werden, die sie anzeigt.
  • Das Paint-Objekt enthält die Stil- und Farbinformationen zum Zeichnen von Geometrien (z. B. Linien, Rechtecke, Ovale und Pfade) und Text.
  • Ein gängiges Muster für die Arbeit mit einem Canvas ist das Erstellen einer benutzerdefinierten Ansicht und das Überschreiben der Methoden onDraw() und onSizeChanged().
  • Überschreiben Sie die Methode onTouchEvent(), um Nutzerberührungen zu erfassen und darauf zu reagieren, indem Sie Elemente zeichnen.
  • Sie können ein zusätzliches Bitmap verwenden, um Informationen für Zeichnungen zu speichern, die sich im Laufe der Zeit ändern. Alternativ können Sie Formen oder einen Pfad speichern.

Udacity-Kurs:

Android-Entwicklerdokumentation:

In diesem Abschnitt werden mögliche Hausaufgaben für Schüler und Studenten aufgeführt, die dieses Codelab im Rahmen eines von einem Kursleiter geleiteten Kurses durcharbeiten. Es liegt in der Verantwortung des Kursleiters, Folgendes zu tun:

  • Weisen Sie bei Bedarf Aufgaben zu.
  • Teilen Sie den Schülern/Studenten mit, wie sie Hausaufgaben abgeben können.
  • Benoten Sie die Hausaufgaben.

Lehrkräfte können diese Vorschläge nach Belieben nutzen und auch andere Hausaufgaben zuweisen, die sie für angemessen halten.

Wenn Sie dieses Codelab selbst durcharbeiten, können Sie mit diesen Hausaufgaben Ihr Wissen testen.

Beantworten Sie diese Fragen

Frage 1

Welche der folgenden Komponenten sind für die Arbeit mit einem Canvas erforderlich? Wähle alle zutreffenden Antworten aus.

▢ Bitmap

▢ Paint

▢ Path

▢ View

Frage 2

Was passiert bei einem Anruf an invalidate() (allgemein)?

▢ Ihre App wird ungültig und neu gestartet.

▢ Löscht die Zeichnung aus der Bitmap.

▢ Gibt an, dass der vorherige Code nicht ausgeführt werden soll.

▢ Weist das System an, den Bildschirm neu zu zeichnen.

Frage 3

Welche Funktion haben die Objekte Canvas, Bitmap und Paint?

▢ 2D-Zeichenfläche, auf dem Bildschirm angezeigte Bitmap, Formatierungsinformationen für das Zeichnen.

▢ 3D-Zeichenfläche, Bitmap zum Zwischenspeichern des Pfads, Styling-Informationen zum Zeichnen.

▢ 2D-Zeichenfläche, auf dem Bildschirm angezeigte Bitmap, Stil für die Ansicht.

▢ Cache für Zeicheninformationen, Bitmap zum Zeichnen, Styling-Informationen zum Zeichnen.

Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage für Codelabs zum Thema „Android für Fortgeschrittene mit Kotlin“.