Android-Programmierung GUI: Layout
Willemers Informatik-Ecke
Zurück zur Android-Hauptseite

Die Gestaltung eines Displays wird folgendermaßen realisiert:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_xxx);
Das xxx im Listing steht für das Display der Activity. Beim Haupt-Display ist xxx durch main zu ersetzen.

Auch ein Fragment nutzt eine XML-Datei für das Design. Das Fragment ruft in seiner Handler-Methode onCreateView die Methode inflate auf.

Nach dem Anlegen eines Projekts erstellt Android-Studio den Programmrahmen für die Haupt-Activity und gleichzeitig die Datei res/layout/activity_main.xml.

Der Editor für das Layout

Klickt man auf diese Datei wird diese auf drei Arten dargestellt, die über Symboltasten rechts oben umschaltbar sind:

Anordnung in einer ViewGroup

Eine XML-Datei fasst ein oder mehrere Kontrollelemente zusammen, die unter Android als View bezeichnet werden. Den Rahmen einer solchen XML-Datei bildet eine ViewGroup, die festlegt, wie die Kinder, also die Views, angeordnet werden. Beim Erzeugen eines Projekts erzeugt Android-Studio eine XML für die Main-Activity, die ein TextView-Kontrollelement in einer ViewGroup mit ConstraintLayout enthält und etwa so aussieht:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Ausdehnung

android:layout_width und android:layout_height geben die Breite und Höhe des Elements an.

Abstände

Die Views können auf zwei Arten Abstand schaffen:

Einheiten

Gängige Einheiten beispielsweise für Abstände sind

Diese Einheiten führen dazu, dass Anwendungen auf verschiedenen Geräten keine Probleme bereiten, sondern etwa gleich aussehen.

Möglich sind auch die Einheiten mm, in, pt (Punkt - Eine Einheit aus dem Druckbereich). Allerdings sind diese nicht unabhängig von der Geräte-Hardware und sollten darum vermieden werden.

Identifikation

Jedes Element eines Layouts kann über eine ID gekennzeichnet werden. Das geschieht durch Hinzufügen einer android:id.
android:id="@+id/meinElement"
Diese ID ist wichtig, wenn man vom Java-Programm das Kontrollelement auslesen oder setzen will, aber auch, wenn das Verhältnis von Elementen innerhalb des Layouts definiert werden sollen:
app:layout_constraintStart_toEndOf= "@id/meinElement"

LinearLayout

In einem LinearLayout werden die Elemente immer untereinander oder nebeneinander angeordnet. Die Richtung wird durch das Orientation-Attribut bestimmt. Dessen Wert kann horizontal oder vertical sein.
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical" >

    ...

</LinearLayout>
Alle Kindelemente müssen android:layout_width und android:layout_height definieren:
<TextView
    android:layout_width  = "match_parent"
    android:layout_height = "wrap_content" />
Das LinearLayout wird aufgrund seiner einfachen Handhabung gern verwendet, um mit anderen Layouts verschachtelt zu werden. Hohe Verschachtelung macht den Neuaufbau des Bildschirms aufwändig. Insofern kann es sich aus aus Performance-Gründen lohnen, komplexere Layouts zu verwenden.

RelativeLayout

Im RelativeLayout werden die Elemente im Verhältnis zu anderen Elementen angelegt, also beispielsweise unter einem Button oder links von einer TextView.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

...
    <EditText
        android:id="@+id/edSpielername"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/spielerliste"
        android:singleLine="true"
        android:layout_toRightOf="@+id/textView"
        android:layout_toEndOf="@+id/textView"
        />
...

</RelativeLayout>
In den Elementen können folgende Relationen angegeben werden.
android:layout_above Das Element liegt über dem anderen Element.
android:layout_below Das Element liegt unter dem anderen Element.
android:layout_toLeftOf Das Element liegt links von dem anderen Element.
android:layout_toRightOf Das Element liegt rechts von dem anderen Element.
android:layout_toStartOf Das Element richtet sich nach dem Anfang dem anderen Elements aus. Die Elemente beginnen also in der gleichen vertikalen Position.
android:layout_toEndOf Das Element richtet sich nach dem Ende des anderen Elements aus.

ConstraintLayout

Das ConstraintLayout organisiert seine Elemente durch Constraints, die das Verhältnis von Elementen beschreiben. Auf diese Weise ist es noch etwas flexibler als das RelativeLayout.

Der Vorteil dieses komplexen Layouts ist, dass vielfach das Verschachteln von Layouts umgangen werden kann. So sind die Strukturen flach und effizienter darzustellen.

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    ...

</android.support.constraint.ConstraintLayout>
Die Elemente können Beziehungen zwischen seinen Kanten Start oder End bzw. Top zu Kanten (Bottom zu Start oder End bzw. Top) anderer Elemente, auch der des Elternelements (parent) definieren.

app:layout_constraintStart_toStartOf= "parent"
app:layout_constraintStart_toEndOf= "@id/cancel_button"
app:layout_constraintTop_toTopOf= "parent"
app:layout_constraintTop_toBottomOf= "@id/recyclerView"
app:layout_constraintEnd_toEndOf= "parent"
app:layout_constraintBottom_toTopOf= "@id/ok_button"
app:layout_constraintBottom_toBottomOf= "parent"

Chains

Sollen mehrere Elemente in einer Zeile gleichmäßig verteilt werden, können diese markiert werden und dann mit der rechten Maustaste der Punkt Chains|Horizontal Chain ausgewählt werden.

Verschachteln von Layouts

Layouts können verschachtelt werden. So kann innerhalb des RelativeLayouts auch ein oder mehrere andere Layouts liegen, wie hier ein LinearLayout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
    <Button
        android:id="@+id/bermudaview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
...
</LinearLayout>
Innerhalb des LinearLayouts liegen die Kontrollelemente, wie hier ein Button.

Beispiel: Buttons nebeneinander mittig ausrichten

Das folgende Beispiel enthält eine CheckBox und soll darunter zwei Buttons nebeneinander positionieren. Diese sollen gleichmäßig aussehen.

Damit Buttons in der Horizontalen den Platz (halbwegs) gleichmäßig ausnutzen, legt man ein horizontales LinearLayout an. Darin wird über das Gewicht (weight) bestimmt, welcher Button breiter werden muss als die anderen. Sind die Gewichte alle gleich, richten sie sich gleichmäßig aus.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".SpielerActivity">

    ...
    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/virtuell"
        android:id="@+id/ckAutomat"
        android:layout_below="@+id/ed...."
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="3"
        android:layout_below="@+id/ckAutomat"
        >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/change"
        android:id="@+id/btChange"
        android:layout_weight="1"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/add"
        android:layout_weight="1"
        android:id="@+id/btAdd"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/del"
        android:id="@+id/btDel"
        android:layout_weight="1"
        />
    </LinearLayout>

</RelativeLayout>

Data-Binding

Ein Layout kann Kontrollelemente mit deren Datenquellen verbinden.
  1. dataBinding muss in der Manifest-Datei eingeschaltet werden.
    android {
        ...
        databinding.enabled = true
    }