Android-Programmierung: Canvas
Willemers Informatik-Ecke

Die Canvas ermöglicht das Zeichnen auf dem Android-Smartphone. Sie enthält die wichtigen Informationen über die Zeichenumgebung, beispielsweise die Größe des Displays.

Canvas als Parameter von onDraw

Auf der Canvas kann in der Methode onDraw gezeichnet werden, die von der Klasse View implementiert wird und bei eigenen Views typischerweise überschrieben wird.
@Override
public void onDraw(Canvas canvas) {

}
Die Ausmaße des Zeichenbereichs lassen sich über die Methoden getWidth() für die Breite und getHeight() für die Höhe ermitteln.

@Override
public void onDraw(Canvas canvas) {
    float width = canvas.getWidth();
    float height = canvas.getHeight();
Das Koordinatensystem hat ihren Ursprung links oben. Das bedeutet, dass eine höhere y-Koordinate weiter unten liegt.

Zeichenattribute in Paint

Ein Objekt der Klasse Paint wird bei jedem Grafikaufruf übergeben. Sie können es beispielsweise verwenden, um mit setColor die Farbe einzustellen. Dazu muss es aber zunächst erstellt werden.

Farbe

private Paint paint = new Paint();
paint.setColor(Color.RED);
Für die Standardfarben bietet die Klasse Color Konstanten. Sollen die Farben per RGB angegeben werden, wird einfach der hexadezimale Wert angegeben. Zusätzlich zu den drei Byte für den RGB-Wert wird als Highbyte noch die Transparenz angegeben, bei voller Intensität ist diese ff.
private Paint paint = new Paint();
paint.setColor(0xff0000ff); // aarrggbb, hier volldeckendes Blau
Ganz ideal hinterlegt man die Farbwerte in einer XML-Datei.
int color = ContextCompat.getColor(context, R.color.meinefarbe);
paint.setColor(color);
Diese Farbe wird aus der XML-Datei res/values/color.xml geholt.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="meinefarbe">#0000FF</color>
</resources>

Füllen oder Umrisse

Standardmäßig werden alle Grafikobjekte gefüllt gezeichnet. Will man nur die Umrisslinien, muss der Style auf STROKE umgestellt werden. Dies erreicht man mit der Methode setStyle, die über drei Möglichkeiten verfügt.
paint.setStyle(Paint.Style.STROKE);
paint.setStyle(Paint.Style.FILL);
paint.setStyle(Paint.Style.FILL_AND_STROKE);

Textattribute

Man kann auch mit setTextSize() die Schriftgröße einstellen. Als Parameter wird die Größe übergeben.

Textgröße aus der dimens.xml beziehen

Es ist allerdings sinnvoll, diese Größe in der Datei values/dimens.xml vorzugeben, weil sie dann leichter an die Auflösung und Größe des Displays angepasst werden kann.
int fontSize = getContext().getResources().getDimensionPixelSize(R.dimen.grossSchrift);
paint.setTextSize(fontSize);
Dazu erhält die Datei values/dimens.xml den folgenden Eintrag:
<resources>
...
    <dimen name="grossSchrift">30sp</dimen>
</resources>

Die Zeichenmethoden des Canvas

Die Zeichenprimitive werden über das Canvas-Objekt aufgerufen, das als Paramter der Methode onDraw übergeben wird. Der letzte Parameter ist immer ein Paint-Objekt, das zuvor erstellt werden muss. Alle Koordinaten der Aufrufe sind vom Typ float.

Linien ziehen: drawLine

Die Linie wird mit der Anfangs- und Endkoordinate festgelegt.
canvas.drawLine(xAnfang, yAnfang, xEnde, yEnde, paint);

Rechteck: drawRect

Für das Zeichnen eines Rechtecks wird zunächst ein Rechteck-Objekt der Klasse RectF (mit float-Koordinaten) oder Rect (mit int-Koordinaten) angelegt. Dieses wird der Methode drawRect als erster Parameter übergeben.
RectF rect = new RectF(links, oben, rechts, unten);
canvas.drawRect(rect, paint);

Ellipse: drawOval

Die Methode drawOval zeichnet eine Ellipse. Dazu erhält sie als Parameter das Rechteck, das den Außenrahmen der Ellipse darstellt.
RectF rect = new RectF(links, oben, rechts, unten);
canvas.drawOval(rect, paint);

Kreis: drawCircle

Die Methode drawCircle zeichnet einen Kreis und benötigt als Parameter die Koordinaten des Mittelpunkts und den Radius. Auch hier wird ein Objekt von Paint als letzter Parameter benötigt.
canvas.drawCircle(x, y, radius, paint);

Texte: drawText

Mit der Methode drawText können Grafiken beschriftet werden. Größe und andere Parameter der Schrift müssen zuvor im Paint-Objekt festgelegt werden.
String text = ...
canvas.drawText(text, x, y, paint);
x beschreibt den Abstand vom linken Rand. y ist die Position der Basiszeile. Das Bedeutet, dass Unterlängen wie beim kleinen g unterhalb der Position sind.

Bilder: drawBitmap

Das Bild wird im Projekt im Verzeichnis /res/drawable abgelegt. Als Bildformat eignen sich unter anderem jpg, gif oder png.

Bild in Originalgröße zeichnen

Bitmap bitmap = BitmapFactory.decode(getResources(), R.drawable.bild);
Rect rect = new Rect(0, 0, bitmap.getWidth() bitmap.getHeight());
rect.offsetTo(xOffset, yOffset);
canvas.drawBitmap(bitmap, null, rectBild, paint);

Bitmap soll die View als Hintergrund füllen

Das Beispiel füllt den Hintergrund flächendeckend ohne Rücksicht auf die Ratio. Das Bild ist also verzerrt.
// Bild aus der Ressource laden
Bitmap bitmap = BitmapFactory.decode(getResources(), R.drawable.bild);
Rect rectBild = new Rect(); // Ein Rechteck für das Bild
// Rechteck auf Bildgröße anpassen
rectBild.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
// Ein Rechteck für die View anpassen.
Rect rectView = new Rect();
rectView.set(0, 0, this.getWidth(), this.getHeight());
canvas.drawBitmap(bitmap, rectBild, rectView, paint);
Um das Image maximal ohne Verzerrung darzustellen, muss das Verhältnis zwischen Höhe und Breite der View und andererseits der Bitmap ermittelt werden. Das rectView muss nun in Abhängigkeit, welches Verhältnis größer ist, so angepasst werden, dass die Dimensionen optimal in die View passen.

Da dies eine Aufgabe der Veranstaltung Mobile Computing der Hochschule Flensburg ist, möchte ich die Lösung hier nicht spoilern.