Benutzerschnittstellen
Einleitung
Benutzerschnittstellen bestehen in Android aus sogenannten Views und
Gruppierungen von Views. Dazu werden die Klassen
android.view.View
und
android.view.ViewGroup
bereit gestellt. Durch Ableitung von diesen Klassen werden konkrete
Elemente der Benutzerschnittstelle erzeugt. Dazu gehören unter
anderem die Klassen
Button
,
CheckBox
,
LinearLayout
,
TabWidget
und viele weitere. Views bilden eine Hierarchie. Das heißt, jedes
Elemente kann optional Kindelemente besitzen.
Android bietet die Möglichkeit, Benutzerschnittstellen statisch oder programmatisch zu erzeugen. Statisch bedeutet, dass mittels XML-Dateien die Schnittstelle beschrieben wird. Damit können viele Einsatzgebiete bereits abgedeckt werden. Es kann aber auch nötig sein, eine Benutzerschnittstelle erst an Hand bestimmter Eingabedaten zur Laufzeit zu generieren. Dies kann getan werden, indem konkreter Java-Code zur Instanziierung der GUI-Elemente programmiert wird. Es ist aber auch möglich, XML-basierte Views zur Laufzeit programmatisch zu verändern.
In diesem Tutorial wird eine einfache grafische Benutzeroberfläche erstellt. Diese wird im Kern aus XML-basierten Elementen bestehen. Durch ein Menu und Ereignisse wird zwischen verschiedenen Ansichten, Activities genannt, gewechselt. Auch die programmatische Erstellung einiger Teile wird vorgestellt.
Layouts
Layouts beschreiben die Anordnung von Elementen der
Benutzeroberfläche. Dies geschieht vorrangig durch
XML-Beschreibungen. Diese können per Hand oder durch einen grafischen
Editor, welcher durch die Android Development Tools bereitgestellt
wird, erzeugt werden. Am häufigsten wird das
LinearLayout
verwendet. Dieses ordnet seine Kindelemente nacheinander entweder
horizontal oder vertikal an.
Nach der Erstellung eines neuen Projekts wird die Datei main.xml aus dem Ordner res/layout
geöffnet. Es öffnet sich der grafische GUI Editor. Mittels Drag 'n'
Drop fügen wir der GUI nun ein
Texview
und einen
Button
hinzu:
Mit einem Rechtsklick auf ein Element kann mit dem Menupunkt Edit ID die ID des Elementes geändert werden:
Ereignisse
Beispielhaft für die Arbeit mit Ereignissen verwenden wir
Button-Clicks. Um auf ein Ereignis zu reagieren, benötigen wir einen
Listener. Um diesen zu erstellen, gibt es zwei Möglichkeiten. Die
erste besteht darin, in der Methode
onCreate()
der Activity eine Referenz auf den Button zu erhalten und diesem mit
der Methode
setOnClickListener()
einen Listener zuzuweisen. Die zweite Möglichkeit ist die Zuweisung
über den grafischen Editor. Um beide Möglichkeiten zu zeigen, wird
der Benutzeroberfläche zuerst ein zweiter Button hinzugefügt. Die
ID's der Buttons werden auf "button1" und "button2" geändert. Der
erste Button soll programmatisch einen Listener zugeordnet bekommen.
Beim zweiten Button wird dies per Editor erledigt. In beiden Fällen
soll sich der Text in dem Textview-Objekt ändern.
Das Layout sollte im XML-Code etwa wie folgt aussehen:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button1" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button2" /> </LinearLayout>
Programmatische Zuweisung eines Listeners
Um einen Listener programmatisch zuzuweisen, muss die Methode
onCreate()
angepasst werden. Zuerst wird eine Referenz auf den ersten Button
benötigt. Dazu nutzt man die Methode
findViewById
. Anschließend kann der Listener erzeugt werden, ähnlich wie in
Swing-Applikationen. Innerhalb des Listeners werden wir wie im Tutorial über Activities eine
Nachricht ausgeben. Der Quelltext der Activity sieht anschließend wie
folgt aus:
package de.hszg.mobileapps.ui; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class UITestActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(getApplicationContext(), "Button 1 wurde gedrückt", Toast.LENGTH_LONG).show(); } }); } }
Listener per Editor setzen
Um per Editor einen Listener zu setzen, klickt man rechts auf den Button (Button 2) und wählt die Eigenschaft "OnClick" aus, wie in der folgenden Abbildung ersichtlich:
Im sich öffnenden Fenster gibt man den Namen der aufzurufenden
Methode an, zum Beispiel
onButtonClicked
. Dieser Name wird nun automatisch in die XML-Datei eingetragen:
<Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="onButtonClicked" android:text="@string/button2" />
Startet man die App nun und klickt auf den zweiten Button, so erhält
man eine Fehlermeldung, da die angegebene Methode ja noch nicht
angelegt wurde. In der Activity wird nun eine Methode mit Namen
onButtonClicked
angelegt. Diese erwartet als Parameter ein Objekt vom Typ
View
:
public void onButtonClicked(View v) { Toast.makeText(getApplicationContext(), "Button 2 wurde gedrückt", Toast.LENGTH_LONG).show(); }
Beide Varianten, um Ereignisse mit Listenern zu verbinden werden in der Praxis eingesetzt. Welche von beiden sollte man nun wählen? Wann immer möglich, ist die zweite Variante zu bevorzugen, da der Java-Code besser lesbar bleibt. Die programmatische Variante wird normalerweise nur gewählt, wenn auch die entsprechenden Elemente der Benutzeroberfläche programmatisch erzeugt wurden, und somit das Setzen des Listeners per Editor nicht möglicht ist.
Menus
Im Folgenden wird ein einfaches Menu erstellt, mit dem von der Haupt-Activity zu einer anderen Activity gewechselt werden kann. Dazu erstellt man im Ordner res einen Unterordner menu. Mittels Rechtsklick auf den neu erstellten Ordner fügt man nun eine neue Android XML Datei mit dem Typ "Menu" hinzu:
Im Editor wird nun ein neues Menu-Item hinzugefügt und ein Titel
angegeben. Damit das Menu angezeigt wird, muss die Methode
onCreateOptionsMenu()
implementiert werden:
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); return true; }
Die Aktionen, welche bei Auswahl eines Menuelementes geschehen sollen, werden in einer weiteren Methode implementiert.
Diese nennt sich onOptionsItemSelected()
. Als Parameter erhält man das ausgewählt Menu-Item. Mit einer switch-Anweisung
kann nun das die auszuführende Aktion bestimmt werden. Im konkreten Fall soll eine neue Activity gestartet werden. Wir
verwenden die eine bereits existierende Activity:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.item1: Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } }