Steuerungstasten

nächste Folie (auch Enter oder Spacebar).
vorherige Folie
 d  schaltet das Zeichnen auf Folien ein/aus
 p  wechselt zwischen Druck- und Präsentationsansicht
CTRL  +  vergrößert die Folien
CTRL  -  verkleinert die Folien
CTRL  0  setzt die Größenänderung zurück

Das Weiterschalten der Folien kann ebenfalls durch das Klicken auf den rechten bzw. linken Folienrand erfolgen.

Android

androidicon
  • Android ist ein auf Linux basierendes Betriebssystem von Google mit sehr großer Verbreitung auf mobilen Geräten (88% aller Smartphones in Q2/2018*)
  • Eigene Anwendungen (Apps) können in Java mit dem Android Software Development Kit (SDK) erstellt werden, das alle benötigten Werkzeuge und Bibliotheken enthält
  • Das SDK gibt es für alle gängigen Plattformen (Windows, Mac OS und Linux)
  • Auf der Android Developer Webseite sind detaillierte Anleitungen und Hilfestellungen zu finden

Android Studio installieren

  • Google hat die Unterstützung der bisherigen Stand-alone SDK Tools und der Android Eclipse Tools eingestellt.
  • Entwickler müssen jetzt mit Android Studio arbeiten:

Android Projekt-Verzeichnis erzeugen

  • Der Quellcode einer App besteht nicht nur aus Java-Dateien, sondern aus einer Verzeichnisstruktur mit diversen XML-Dateien, Bilddateien für Icons, etc.
  • Zum Erzeugen einer initialen Verzeichnisstruktur für ein Projekt kann Android Studio verwendet werden
    (Anleitung)

AndroidManifest.xml

  • Die Manifest-Datei AndroidManifest.xml innerhalb der erzeugten Verzeichnisstruktur ist besonders wichtig
  • Sie legt fest, wie die Applikation heisst, welches Icon verwendet wird, welche Activity beim Start des Programms ausgeführt wird, welche Styles verwendet werden, usw.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="de.unimarburg.helloguiapp"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:label="HelloGUIApp">
        <activity android:name="HelloGUI"
                  android:label="HelloGUIApp">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>;

AndroidManifest.xml

  • Wenn die App später auf verschiedenen Geräten lauffähig sein soll, kann die Manifest-Datei festlegen, welche Android-Version mindestens auf dem Gerät vorhanden sein muss (android:minSdkVersion) und was die höchste Android-Version ist, die der Entwickler getestet hat (android:targetSdkVersion)
  • Dazu wird folgende Zeile eingefügt:
<?xml version="1.0" encoding="utf-8"?>
<manifest ....>
   <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="20" />
...
</manifest>
  • Die App steht dann innerhalb von Google Play nur auf solchen Geräten zur Verfügung, die den Anforderungen entsprechen
  • Eine vollständige Liste an Google Play Filtern ist hier zu finden

Das erste GUI

Das erste GUI

  • Erzeugung einer Activity als Bildschirm füllender Top-Level-Container
  • Darstellung eines Textes mittels TextView
gui1 gui1

Quelltext des Beispiels: HelloGUI.zip

Das erste GUI

package de.unimarburg.helloguiapp;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloGUI extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText("Hello World");
        setContentView(tv);
    }
}

Hinzufügen eines Menüs

  • Erstellen eines Menüs mit Menu und SubMenu
menubar


Quelltext des Beispiels: MyMenuBar.zip

Hinzufügen eines Menüs

package de.unimarburg.mymenubarapp;
import android.app.Activity;
...
public class MyMenuBar extends Activity {
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView tv = new TextView(this);
    tv.setText("Hello World");
    setContentView(tv);
  }
  public boolean onCreateOptionsMenu(Menu menu) {
    SubMenu subMenu = menu.addSubMenu("File");
    subMenu.add("Open");
    subMenu.add("Close");
    return true;
  }
}  

Vererbungshierarchie ("ist ein") für die Android View-Klasse

class_hierarchy
Quelle: extrahiert aus Android API

Layout-Manager

  • Der Funktion setContentView einer Activity kann nur ein View übergeben werden
  • Sollen mehrere Komponenten platziert werden, muss ein Layout-Manager verwendet werden
  • Ein Layout-Manager automatisiert das Platzieren von Komponenten
  • Das Layout wird automatisch angepasst, wenn sich die Fenstergröße verändert
  • Bei Android sind alle Layouts und Container von der Klasse View.ViewGroup abgeleitet

Hinzufügen eines Buttons

  • Erstellen einer Schaltfläche mit der Klasse Button
button


Quelltext des Beispiels: MyButton.zip

Hinzufügen eines Buttons

public class MyButton extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    TextView tv = new TextView(this);
    tv.setText("Hello World");
    layout.addView(tv);
    Button b = new Button(this);
    b.setText("Button Text");
    layout.addView(b);
    LinearLayout.LayoutParams lp;
    lp = (LinearLayout.LayoutParams) b.getLayoutParams();
    lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
    this.setContentView(layout);
  }
 ...
}

Kompositionshierarchie für das Beispiel ("ist Teil von")

containment_hierarchy
button

XML-Beschreibung

XML-Beschreibung für GUI-Komponenten

  • Statt die GUI-Komponenten, wie bisher gezeigt, im Programm-Code zu instanziieren, kann die Kompositionshierarchie auch mittels Resource-Dateien im XML-Format beschrieben werden
  • Vorteile
    • Die graphischen Layout-Editoren aus den integrierten Entwicklungsumgebungen können XML leicht lesen und schreiben
    • Es können verschiedene Layouts für verschiedene Sprachen, Bildschirmgrößen oder die Orientierung eines Gerätes hinterlegt werden
    • Die XML-Beschreibung entkoppelt das GUI-Design von der Programmierung der Funktionalität
  • Nachteile
    • Mehr Dateien
    • Aufwendigeres Build-System, da die Resource-Dateien getrennt kompiliert werden müssen
    • Viele gleichartige Komponenten können nicht durch Programm-Schleifen instanziiert werden

Resource-Dateien

  • Die Resource Dateien sind in einer Verzeichnisstruktur innerhalb des Verzeichnisses ./res/ abgelegt
    • ./res/layout/ für die XML-Layouts
    • ./res/menu/ für Menü-Strukturen
    • ./res/values/ für konstante Werte für Strings, Farben, Zahlen, Arrays, etc.
    • ./res/drawable/ für Bilddaten
  • Zusätzliche Kennzeichner, die in den Verzeichnisnamen kodiert werden, beschreiben Ressourcen für verschiedene Geräte, z.B.,
    • ./res/values-de/ für deutsche Strings, usw.
    • ./res/drawable-ldpi/ für Bilddaten (niedrige Auflösung)
    • ./res/drawable-mdpi/ für Bilddaten (mittlere Auflösung)
    • ./res/drawable-hdpi/ für Bilddaten (hohe Auflösung)
    • ./res/drawable-xhdpi/ für Bilddaten (besonders hohe Auflösung)
  • Während des Build-Prozesses wird aus den Ressourcen eine Datei R.java erzeugt, die die Klasse R enthält, auf die im Programm-Code zugegriffen werden kann

Das bisherige Beispiel mit XML-Ressourcen

button


Quelltext des Beispiels: MyButtonAlt.zip

Das bisherige Beispiel mit XML-Ressourcen

Datei: ./res/values/mybuttonstrings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="textViewString">Hello World</string>
    <string name="buttonString">Button Text</string>
    <string name="menuFile">File</string>
    <string name="menuOpen">Open</string>
    <string name="menuClose">Close</string>
</resources>

Datei: ./res/menu/mybuttonmenu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/file"
          android:title="@string/menuFile" >
        <menu>
            <item android:id="@+id/open"
                  android:title="@string/menuOpen" />
            <item android:id="@+id/close"
                  android:title="@string/menuClose" />
        </menu>
    </item>
</menu>

Das bisherige Beispiel mit XML-Ressourcen

Datei ./res/layout/mybuttonlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/textViewString" />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/buttonString" />
</LinearLayout>
  • Das '@'-Zeichen referenziert auf andere XML-Ressourcen
  • Um ein Element eindeutig im Code zu referenzieren, wird eine eindeutiger Kennzeichner (ID) benötigt. Durch das '+'-Zeichen wird diese ID automatisch angelegt.

Das bisherige Beispiel mit XML-Ressourcen

Der eigentliche Java-Quelltext wird durch Verwendung der XML-Beschreibung häufig kürzer:

package de.unimarburg.mybuttonaltapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;

public class MyButtonAlt extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mybuttonlayout);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.mybuttonmenu, menu);
    return true;
  }
}

Ereignisverarbeitung

Ereignisverarbeitung

  • Ereignis (Event): Etwas wurde aktiviert, verändert, bewegt, etc.
  • Ereignisquelle: Die Komponente, von der das Ereignis ausgeht, z.B. ein gedrückter Button
  • Ereignisbeobachter: Die Klasse, die von dem Ereignis informiert werden möchte

Ereignisverarbeitung

  • Bei Android gibt es zwei Arten, um eine Ereignisverarbeitung zu realisieren:
    • Event Handlers: Dazu muss eine eigene Klasse von der Klasse View oder dessen Kinderklassen abgeleitet werden und die entsprechenden Funktionen, wie z.B. onKeyDown(int keyCode, KeyEvent event), überschrieben werden
    • Event Listeners: Dazu muss ein Interface implementiert werden, z.B.
      OnKeyListener kl = new OnKeyListener() {
        @Override
        public boolean onKey (View clickedView, int keyCode, KeyEvent event) {
         ...
        }
      };
      Diese Event-Listener-Instanz kann anschließend an eine oder mehrere Ereignisquellen übergeben werden durch View.setOnKeyListener(kl).

Hinzufügen einer Ereignisverarbeitung für den Button

  • Ein Klick auf den Button erhöht einen Zähler und gibt den Zählerstand im TextView aus
actionbutton

Quelltext des Beispiels: ActionButton.zip

Hinzufügen einer Ereignisverarbeitung für den Button

package de.unimarburg.actionbuttonapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.SubMenu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.LinearLayout;

public class ActionButton extends Activity {
  
  private int counter = 0;
  TextView tv;
  
  private OnClickListener cl = new OnClickListener() {
    @Override
    public void onClick(View v) {
      counter++;
      tv.setText("Click #" + Integer.toString(counter));
    } 
  };
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    tv = new TextView(this);
    tv.setText("Hello World");
    layout.addView(tv);
    Button b = new Button(this);
    b.setText("Increment");
    b.setOnClickListener(cl);
    layout.addView(b);
    LinearLayout.LayoutParams lp;
    lp = (LinearLayout.LayoutParams) b.getLayoutParams();
    lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
    this.setContentView(layout);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    SubMenu subMenu = menu.addSubMenu("File");
    subMenu.add("Open");
    subMenu.add("Close");
    return true;
  }
}

Hinzufügen einer Ereignisverarbeitung für das Menü

  • Die Auswahl des MenuItem "Reset" setzt den Zähler zurück.
gui_action_menu


Quelltext des Beispiels: ActionMenu.zip

Hinzufügen einer Ereignisverarbeitung für das Menü

public class ActionMenu extends Activity {
  ...
  private final int ID_MENU_INC = 1;
  private final int ID_MENU_RST = 2;
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(Menu.NONE, ID_MENU_INC, Menu.NONE, "Increment");
    menu.add(Menu.NONE, ID_MENU_RST, Menu.NONE, "Reset");
    return true;
  }
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    counter++;
    if(item.getItemId() == ID_MENU_RST) counter = 0;
    tv.setText("Click #" + Integer.toString(counter));
    return true;
  }
}

Berührungen, Bewegungen und Gesten

  • Die Klasse MotionEvent dient dazu, Berührungen und Bewegungen mit Finger, Stift oder Maus zu beschreiben
  • MotionEvents können z.B. an einen GestureDetector.SimpleOnGestureListener weitergeleitet werden, um bestimmte Gesten zu erkennen:
    • onDown(MotionEvent e): Benutzer hat den Bildschirm berührt
    • onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY): Benutzer hat eine Wischbewegung ausgeführt
    • onLongPress(MotionEvent e): Benutzer hat den Bildschirm lange berührt
    • onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY): Benutzer hat eine Scrollbewegung ausgeführt
    • onShowPress(MotionEvent e): Benutzer hat den Bildschirm angetippt und weder bewegt noch losgelassen
    • onSingleTapUp(MotionEvent e): Benutzer hat den Bildschirm angetippt und wieder losgelassen

Beispiel: TouchEvent

  • Beim Berühren des Bildschirms wird die Position in einem TextView ausgegeben
gui_motionevent

Quelltext des Beispiels: MyTouchEvent.zip

Beispiel: TouchEvent

package de.unimarburg.mytoucheventapp;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.view.GestureDetector;
import android.view.MotionEvent;

public class MyTouchEvent extends Activity {

  private GestureDetector gestDetector;
  private TextView tv;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    tv = new TextView(this);
    tv.setText("Position: 0, 0");
    setContentView(tv);
    MyGestureListener gl = new MyGestureListener();
    gestDetector = new GestureDetector(this, gl);
  }

  @Override
  public boolean onTouchEvent(MotionEvent e) {
    this.gestDetector.onTouchEvent(e);
    return super.onTouchEvent(e);
  }

  class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
      tv.setText("onFDown; Position=" + Float.toString(e.getX()) + ", "
          + Float.toString(e.getY()));
      return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
      tv.setText("onLongPress; Position=" + Float.toString(e.getX()) + ", "
          + Float.toString(e.getY()));
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
        float velocityY) {
      tv.setText("onFling: from=" + Float.toString(e1.getX()) + ", "
          + Float.toString(e1.getY()) + " to=" + Float.toString(e2.getX())
          + ", " + Float.toString(e2.getY()));
      return true;
    }
  }
}

Lebenszyklus einer Activity

Lebenszyklus einer Activity und Datenmanagement

  • Bei mobilen Geräten wird häufig zwischen den Activities gewechselt. Dies geschieht teilweise ohne explizite Aktion des Benutzers, z.B. bei einem eingehenden Anruf
  • Die Activities sind dabei wie ein Stapel organisiert, wobei nur die oberste "Foreground"-Activity die Benutzereingaben entgegen nimmt
  • Wird eine andere Activity zur "Foreground"-Activity, wird die bisherige Activity pausiert und die Memberfunktion onPause() aufgerufen. Die bisherige Activity ist aber eventuell noch sichtbar
  • Erst wenn die bisherige Activity nicht mehr sichtbar ist, wird diese gestoppt und die Memberfunktion onStop() aufgerufen.
  • Gestoppte oder pausierte Activities können vom Betriebsystem komplett geschlossen werden, um Speicher oder andere Ressourcen freizugeben
  • Daher ist es nötig alle Daten, die für eine Activity permanent gespeichert werden sollen, spätestens in der Memberfunktion onPause() zu speichern (z.B. Benutzer-spezifische Einstellungen, Datenbankeinträge, usw.)
  • Ebenfalls sollten in der Memberfunktion onPause() natürlich alle aufwendigen Berechnungen der Activity gestoppt werden, damit Rechenleistung nicht unnötig vergeudet wird

Lebenszyklus einer Activity

activity_lifecycle
Quelle: basierend auf Android API Guides

Activity Instance State

  • Wenn das Betriebssystem eine Activity komplett schließt, um Ressourcen freizugeben und später wieder neu startet, sollte die Activity möglichst in dem gleichen Zustand sein, in dem der Benutzer sie verlassen hat
  • Dies ist das erwartete Verhalten, da der Nutzer die Activity ja nie selbst geschlossen hat
  • Daher bietet die Activity-Klasse die Memberfunktionen
    onSaveInstanceState(Bundle state) und onRestoreInstanceState(Bundle state), die es erlauben, den aktuellen Zustand dieser speziellen Instanz der Activity in einem Bundle zu speichern und nach einem Neustart daraus wieder herzustellen
  • Alternativ wird das Bundle auch der Funktion onCreate(Bundle state) übergeben, so dass die Wiederherstellung des Zustands auch dort stattfinden kann

Activity Instance State

activity_instancestate
Quelle: basierend auf Android API Guides

Beispiel: SharedPreferences und InstanceState

android_paused_small
  • Das bisherige Zähler-Beispiel wird durch ein Textfeld ergänzt, in das der Benutzer für den Zähler seine Präferenz für die minimale Anzahl der dargestellten Stellen eingeben kann
  • Diese Präferenz wird in der Funktion onPause() in den SharedPreferences gespeichert und beim nochmaligen Starten der App entsprechend gesetzt
  • Ausserdem wird in der Funktion onSaveInstanceState() der aktuelle Zustand des Zähler abgespeichert und bei einem vom Betriebsystem initiierten Neustart in onCreate(Bundle state) wiederhergestellt
  • Ein Neustart kann u.a. durch das Drehen des Geräts (CTRL+F11 oder CTRL+F12 im Emulator) erzwungen werden

Quelltext des Beispiels: PausedActivity.zip

Beispiel: SharedPreferences und InstanceState

...

public class PausedActivity extends Activity {

  private int counter = 0; // this value should be maintained per instance
  private int minDigits = 1; // this preference should be maintained globally
  private TextView tv;
  private EditText et;

  private void updateTextView() {
    tv.setText("Click #" + String.format("%0" + minDigits + "d", counter));
  }

  private OnClickListener cl = new OnClickListener() {
    @Override
    public void onClick(View v) {
      counter++;
      updateTextView();
    }
  };

  private TextWatcher tw = new TextWatcher() {
    @Override
    public void afterTextChanged(Editable s) {
      try {
        minDigits = Integer.parseInt(s.toString());
      } catch (NumberFormatException e) {
        minDigits = 1;
      }
      if (minDigits > 255) {
        minDigits = 255;
      }
      if (minDigits < 1) {
        minDigits = 1;
      }
      updateTextView();
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
  };

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    tv = new TextView(this);
    tv.setText("Hello World");
    layout.addView(tv);

    Button b = new Button(this);
    b.setText("Increment");
    b.setOnClickListener(cl);
    layout.addView(b);
    LinearLayout.LayoutParams lp;
    lp = (LinearLayout.LayoutParams) b.getLayoutParams();
    lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;

    TextView label = new TextView(this);
    label.setText("Choose your preferred minimal number of digits:");
    layout.addView(label);
    et = new EditText(this);
    et.setInputType(InputType.TYPE_CLASS_NUMBER);
    et.setText("1");
    et.addTextChangedListener(tw);
    layout.addView(et);
    lp = (LinearLayout.LayoutParams) et.getLayoutParams();
    lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;

    // if available, restore minDigits from preferences
    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    if (prefs.contains("minDigitsVal")) {
      minDigits = prefs.getInt("minDigitsVal", 1);
      et.setText(Integer.toString(minDigits));
    }

    // if available, restore counter from the savedInstanceState
    if (savedInstanceState != null
        && savedInstanceState.containsKey("counterVal")) {
      counter = savedInstanceState.getInt("counterVal");
      updateTextView();
    } else {
      tv.setText("Hello World");
    }

    this.setContentView(layout);
  }

  @Override
  protected void onPause() {
    super.onPause();
    // write persistent data to preferences
    SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor e = prefs.edit();
    e.putInt("minDigitsVal", minDigits);
    e.commit();
  }

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    // the superclass handles the state of the view classes in the layout
    super.onSaveInstanceState(savedInstanceState);
    // store member variables of this instance to the savedInstanceState
    savedInstanceState.putInt("counterVal", counter);
  }
  ...
}

Canvas

Canvas

  • Zum Zeichnen von 2-dimensionalen Objekten kann eine eigene Klasse von der Klasse View abgeleitet werden und deren onDraw(Canvas canvas) Methode überschrieben werden
  • Die Klasse Canvas enthält diverse Methoden zum Zeichnen von 2D Primitiven, wie Linien, Rechtecken, Kreise, etc.

Beispiel: Linie, Rechteck und Kreis

  • Das Beispiel zeichnet eine Linie, ein Rechteck und einen Kreis
gui_linerectcircle

Quelltext des Beispiels: LineRectCircle.zip

Beispiel: Linie, Rechteck und Kreis

 
  public class MyView extends View {
    Paint paint;
    public MyView(Context context) {
      super(context);
      paint = new Paint();
      paint.setColor(Color.BLACK);
      paint.setStyle(Paint.Style.STROKE);
    }
    @Override
    public void onDraw(Canvas canvas) {
      canvas.drawLine(20.0f, 50.0f, 50.0f, 200.0f, paint);
      canvas.drawRect(100.0f, 50.0f, 60.0f, 80.0f, paint);
      canvas.drawCircle(200.0f, 100.0f, 80.0f, paint);
    }
  }

Beispiel: Zeichnen einer allgemeinen Form

  • Das Beispiel zeichnet ein "T" mit Hilfe der Path Klasse
gui_generalpath

Quelltext des Beispiels: MyGeneralPath.zip

Beispiel: Zeichnen einer allgemeinen Form

public class MyView extends View {
  Paint paint;
  Path path;
  public MyView(Context context) {
    super(context);
    paint = new Paint();
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    //paint.setStyle(Paint.Style.FILL);
    path = new Path(); 
    path.moveTo( 50,  50); // start here
    path.lineTo( 50,  70); // going down
    path.lineTo(100,  70); // going right
    path.lineTo(100, 180); // going down
    path.lineTo(120, 180); // going right
    path.lineTo(120,  70); // going up
    path.lineTo(170,  70); // going right
    path.lineTo(170,  50); // going up
    path.close(); // going left (back to start)
  }
  @Override
  public void onDraw(Canvas canvas) {
    canvas.drawPath(path, paint);
  }
}

Gibt es Fragen?

questions

Anregungen oder Verbesserungsvorschläge können auch gerne per E-mail an mich gesendet werden: Kontakt

Weitere Vorlesungsfolien

Folien auf Englisch (Slides in English)