Layouts in Ansichten
Ein Layout definiert die Struktur für eine Benutzeroberfläche in Ihrer App, z. B. in
einer
Aktivität. Alle Elemente im
Layout werden mit einer Hierarchie von
View und
ViewGroup
Objekten erstellt. Ein View-Objekt zeichnet in der Regel etwas, das der Nutzer sehen und mit dem er interagieren kann. Ein ViewGroup ist ein unsichtbarer Container, der
die Layoutstruktur für View und andere ViewGroup
Objekte definiert, wie in Abbildung 1 dargestellt.
View-Objekte werden oft als Widgets bezeichnet und können eine von
vielen Unterklassen sein, z. B.
Button oder
TextView. Die
ViewGroup Objekte werden in der Regel als Layouts bezeichnet und können einer
von vielen Typen sein, die eine andere Layoutstruktur bieten, z. B.
LinearLayout
oder
ConstraintLayout.
Sie können ein Layout auf zwei Arten deklarieren:
- UI-Elemente in XML deklarieren Android bietet ein einfaches XML
Vokabular, das den
ViewKlassen und Unterklassen entspricht, z. B. für Widgets und Layouts. Sie können auch den Layout-Editor von Android Studio verwenden, um Ihr XML- Layout mit einer Drag-and-drop-Oberfläche zu erstellen. - Layout-Elemente zur Laufzeit instanziieren Ihre App kann
ViewundViewGroupObjekte erstellen und ihre Eigenschaften programmatisch bearbeiten.
Wenn Sie Ihre UI in XML deklarieren, können Sie die Darstellung Ihrer App vom Code trennen, der ihr Verhalten steuert. Außerdem lassen sich mit XML-Dateien leichter verschiedene Layouts für unterschiedliche Bildschirmgrößen und Ausrichtungen bereitstellen. Weitere Informationen finden Sie unter Verschiedene Bildschirmgrößen unterstützen.
Das Android-Framework bietet Ihnen die Flexibilität, eine oder beide dieser Methoden zu verwenden, um die UI Ihrer App zu erstellen. Sie können beispielsweise die Standardlayouts Ihrer App in XML deklarieren und das Layout dann zur Laufzeit ändern.
XML schreiben
Mit dem XML-Vokabular von Android können Sie schnell UI-Layouts und die darin enthaltenen Bildschirmelemente entwerfen, so wie Sie Webseiten in HTML mit einer Reihe verschachtelter Elemente erstellen.
Jede Layoutdatei muss genau ein Stammelement enthalten, das ein
View oder ViewGroup Objekt sein muss. Nachdem Sie das Stammelement definiert haben, können Sie weitere Layoutobjekte oder Widgets als untergeordnete Elemente hinzufügen, um schrittweise eine View-Hierarchie zu erstellen, die Ihr Layout definiert. Hier ist beispielsweise ein XML-Layout, das ein vertikales LinearLayout verwendet, um ein TextView- und ein Button-Objekt zu enthalten:
<?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/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
Nachdem Sie Ihr Layout in XML deklariert haben, speichern Sie die Datei mit der Erweiterung .xml im Verzeichnis res/layout/ Ihres Android-Projekts, damit sie ordnungsgemäß kompiliert wird.
Weitere Informationen zur Syntax für eine XML-Layoutdatei finden Sie unter Layout-Ressource.
XML-Ressource laden
Wenn Sie Ihre App kompilieren, wird jede XML-Layoutdatei in eine View-Ressource kompiliert. Laden Sie die Layout-Ressource in der Activity.onCreate()-Callback-Implementierung Ihrer App. Rufen Sie dazu
setContentView(),
auf und übergeben Sie die Referenz auf Ihre Layout-Ressource im folgenden Format:
R.layout.layout_file_name. Wenn Ihr XML-Layout beispielsweise als main_layout.xml gespeichert ist, laden Sie es für Ihre Activity so:
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
Das Android-Framework ruft die onCreate()-Callback-Methode in Ihrer Activity auf, wenn die Activity gestartet wird. Weitere Informationen zu Aktivitätslebenszyklen finden Sie unter
Einführung in
Aktivitäten.
Attribute
Jedes View und ViewGroup Objekt unterstützt eine eigene
Auswahl an XML-Attributen. Einige Attribute sind spezifisch für ein View-Objekt. TextView unterstützt beispielsweise das Attribut textSize. Diese Attribute werden jedoch auch von allen View-Objekten übernommen, die diese Klasse erweitern. Einige sind für alle View-Objekte gleich, da sie von der Stammklasse View übernommen werden, z. B. das Attribut id. Andere Attribute werden als Layoutparameter betrachtet. Das sind Attribute, die bestimmte Layoutausrichtungen des View Objekts beschreiben, wie sie vom übergeordneten ViewGroup Objekt dieses Objekts definiert werden.
ID
Jedem View-Objekt kann eine Ganzzahl-ID zugewiesen werden, um das View-Objekt im Baum eindeutig zu identifizieren. Wenn die App kompiliert wird, wird auf diese ID als Ganzzahl verwiesen. Die ID wird jedoch in der Regel in der XML-Layoutdatei als String im Attribut id zugewiesen. Dies ist ein XML-Attribut, das für alle View-Objekte gleich ist und von der Klasse View definiert wird. Es wird sehr häufig verwendet. Die Syntax für eine ID in einem XML-Tag sieht so aus:
android:id="@+id/my_button"
Das At-Symbol (@) am Anfang des Strings gibt an, dass
der XML-Parser den Rest des ID-Strings parst und erweitert und ihn als
ID-Ressource identifiziert. Das Pluszeichen (+) bedeutet, dass dies ein neuer Ressourcenname ist, der erstellt und in der Datei R.java zu Ihren Ressourcen hinzugefügt werden muss.
Das Android-Framework bietet viele weitere ID-Ressourcen. Wenn Sie auf eine Android-Ressourcen-ID verweisen, benötigen Sie das Pluszeichen nicht, müssen aber den Paket-Namespace android so hinzufügen:
android:id="@android:id/empty"
Der Paket-Namespace android gibt an, dass Sie auf eine ID aus der Ressourcenklasse android.R und nicht auf die lokale Ressourcenklasse verweisen.
So erstellen Sie Ansichten und verweisen von Ihrer App darauf:
- Definieren Sie eine Ansicht in der Layoutdatei und weisen Sie ihr eine eindeutige ID zu, wie im
folgenden Beispiel:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- Erstellen Sie eine Instanz des Ansichtsobjekts und erfassen Sie sie aus dem Layout,
in der Regel in der
onCreate()Methode, wie im folgenden Beispiel gezeigt:Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
Das Definieren von IDs für Ansichtsobjekte ist wichtig, wenn Sie ein RelativeLayout erstellen.
In einem relativen Layout können gleichgeordnete Ansichten ihr Layout relativ zu einer anderen gleichgeordneten Ansicht definieren, auf die mit der eindeutigen ID verwiesen wird.
Eine ID muss nicht im gesamten Baum eindeutig sein, aber sie muss im Teil des Baums eindeutig sein, den Sie durchsuchen. Oft ist es der gesamte Baum. Daher ist es am besten, sie nach Möglichkeit eindeutig zu machen.
Layoutparameter
XML-Layoutattribute mit dem Namen layout_something definieren
Layoutparameter für das View-Objekt, die für das
ViewGroup-Objekt geeignet sind, in dem es sich befindet.
Jede ViewGroup Klasse implementiert eine verschachtelte Klasse, die
erweitertViewGroup.LayoutParams.
Diese Unterklasse enthält Eigenschaftstypen, die die Größe und Position jeder untergeordneten Ansicht definieren, je nach Ansichtsgruppe. Wie in Abbildung 2 dargestellt, definiert die übergeordnete Ansichtsgruppe Layoutparameter für jede untergeordnete Ansicht, einschließlich der untergeordneten Ansichtsgruppe.
Jede LayoutParams-Unterklasse hat eine eigene Syntax zum Festlegen von Werten. Jedes untergeordnete Element muss ein LayoutParams-Objekt definieren, das für das übergeordnete Element geeignet ist. Es kann aber auch ein anderes LayoutParams-Objekt für seine eigenen untergeordneten Elemente definieren.
Alle Ansichtsgruppen haben eine Breite und Höhe, die mit layout_width und layout_height festgelegt werden. Jede Ansicht muss diese definieren. Viele LayoutParams-Objekte enthalten optionale Ränder und Rahmen.
Sie können Breite und Höhe mit genauen Maßen angeben, aber das ist in der Regel nicht empfehlenswert. Meistens verwenden Sie eine der folgenden Konstanten, um die Breite oder Höhe festzulegen:
wrap_content: Die Ansicht wird so groß wie nötig, um ihren Inhalt aufzunehmen.match_parent: Die Ansicht wird so groß wie die übergeordnete Ansichtsgruppe.
Im Allgemeinen empfehlen wir, Breite und Höhe eines Layouts nicht mit absoluten Einheiten wie Pixeln anzugeben. Besser sind relative Maße wie dichteunabhängige Pixeleinheiten (dp), wrap_content oder match_parent, da Ihre App so auf einer Vielzahl von Geräten mit unterschiedlichen Bildschirmgrößen richtig angezeigt wird. Die akzeptierten Maßeinheiten sind unter
Layout-Ressource definiert.
Layout position
Eine Ansicht hat eine rechteckige Geometrie. Sie hat eine Position, ausgedrückt als Paar von linken und oberen Koordinaten, und zwei Dimensionen, ausgedrückt als Breite und Höhe. Die Einheit für Position und Dimensionen ist das Pixel.
Sie können die Position einer Ansicht abrufen, indem Sie die Methoden getLeft() und getTop() aufrufen.
Die erste Methode gibt die linke (x)-Koordinate des Rechtecks zurück, das die Ansicht darstellt. Die zweite Methode gibt die obere (y)-Koordinate des Rechtecks zurück, das die Ansicht darstellt. Diese Methoden geben die Position der Ansicht relativ zum übergeordneten Element zurück. Wenn getLeft() beispielsweise 20 zurückgibt, befindet sich die Ansicht 20 Pixel rechts vom linken Rand des direkten übergeordneten Elements.
Außerdem gibt es praktische Methoden, um unnötige Berechnungen zu vermeiden: getRight() und getBottom().
Diese Methoden geben die Koordinaten des rechten und unteren Rands des Rechtecks zurück, das die Ansicht darstellt. Der Aufruf von getRight() entspricht beispielsweise der folgenden Berechnung: getLeft() + getWidth().
Größe, Padding und Ränder
Die Größe einer Ansicht wird mit einer Breite und Höhe angegeben. Eine Ansicht hat zwei Paare von Breiten- und Höhenwerten.
Das erste Paar wird als gemessene Breite und gemessene Höhe bezeichnet. Diese Dimensionen definieren, wie groß eine Ansicht innerhalb des übergeordneten Elements sein soll. Sie können die gemessenen Dimensionen mit getMeasuredWidth() und getMeasuredHeight() abrufen.
Das zweite Paar wird als Breite und Höhe oder manchmal
Zeichnungsbreite und Zeichnungshöhe bezeichnet. Diese Dimensionen definieren die tatsächliche Größe der Ansicht auf dem Bildschirm zur Zeichnungszeit und nach dem Layout. Diese Werte können sich von der gemessenen Breite und Höhe unterscheiden, müssen aber nicht. Sie können die Breite und Höhe mit getWidth() und getHeight() abrufen.
Bei der Messung der Dimensionen berücksichtigt eine Ansicht ihr Padding. Das Padding wird in Pixeln für die linke, obere, rechte und untere Seite der Ansicht angegeben.
Mit Padding können Sie den Inhalt der Ansicht um eine bestimmte Anzahl von Pixeln versetzen. Ein linkes Padding von zwei verschiebt den Inhalt der Ansicht beispielsweise um zwei Pixel nach rechts vom linken Rand. Sie können das Padding mit der Methode setPadding(int, int, int, int) festlegen und mit getPaddingLeft(), getPaddingTop(), getPaddingRight() und getPaddingBottom() abfragen.
Eine Ansicht kann zwar ein Padding definieren, aber keine Ränder. Ansichtsgruppen unterstützen jedoch Ränder. Weitere Informationen finden Sie unter
ViewGroup und
ViewGroup.MarginLayoutParams.
Weitere Informationen zu Dimensionen finden Sie unter Dimension.
Neben dem programmatischen Festlegen von Rändern und Padding können Sie sie auch in Ihren XML-Layouts festlegen, wie im folgenden Beispiel gezeigt:
<?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/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
Im vorherigen Beispiel werden Ränder und Padding angewendet. Auf das TextView-Objekt werden einheitliche Ränder und einheitliches Padding angewendet. Das Button-Objekt zeigt, wie Sie sie unabhängig voneinander auf verschiedene Ränder anwenden können.
Häufig verwendete Layouts
Jede Unterklasse der Klasse ViewGroup bietet eine einzigartige Möglichkeit, die darin verschachtelten Ansichten anzuzeigen. Der flexibelste Layouttyp und derjenige, der die besten Tools bietet, um die Layout-Hierarchie flach zu halten, ist ConstraintLayout.
Im Folgenden sind einige der häufig verwendeten Layouttypen aufgeführt, die in die Android-Plattform integriert sind.
Ordnet die untergeordneten Elemente in einer einzelnen horizontalen oder vertikalen Zeile an und erstellt eine Bildlaufleiste, wenn die Länge des Fensters die Länge des Bildschirms überschreitet.
Dynamische Listen erstellen
Wenn der Inhalt für Ihr Layout dynamisch oder nicht vorab festgelegt ist, können Sie RecyclerView oder eine Unterklasse von AdapterView verwenden.
RecyclerView ist in der Regel die bessere Option, da es den Arbeitsspeicher effizienter nutzt als AdapterView.
Häufig verwendete Layouts, die mit RecyclerView und AdapterView möglich sind, sind:
RecyclerView bietet mehr Möglichkeiten und
die Option, einen
benutzerdefinierten
Layout-Manager zu erstellen.
Adapteransicht mit Daten füllen
Sie können ein
AdapterView
wie ListView
oder
GridView füllen, indem Sie die AdapterView Instanz an einen
Adapter binden,
der Daten aus einer externen Quelle abruft und ein View
erstellt, das jeden Dateneintrag darstellt.
Android bietet mehrere Unterklassen von Adapter, die nützlich sind
, um verschiedene Arten von Daten abzurufen und Ansichten für ein
AdapterView zu erstellen. Die beiden häufigsten Adapter sind:
ArrayAdapter- Verwenden Sie diesen Adapter, wenn Ihre Datenquelle ein Array ist. Standardmäßig erstellt
ArrayAdaptereine Ansicht für jedes Array-Element, indemtoString()für jedes Element aufgerufen und der Inhalt in einTextVieweingefügt wird.Wenn Sie beispielsweise ein Array von Strings haben, die in einem
ListViewangezeigt werden sollen, initialisieren Sie ein neuesArrayAdaptermit einem Konstruktor, um das Layout für jeden String und das String-Array anzugeben:Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
Die Argumente für diesen Konstruktor sind:
- Ihrer App
Context - Das Layout, das ein
TextViewfür jeden String im Array enthält - Das String-Array
Rufen Sie dann
setAdapter()für IhrListViewauf:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
Wenn Sie die Darstellung der einzelnen Elemente anpassen möchten, können Sie die
toString()Methode für die Objekte in Ihrem Array überschreiben. Wenn Sie für jedes Element eine andere Ansicht als einTextViewerstellen möchten, z. B. einImageViewfür jedes Array-Element, erweitern Sie die KlasseArrayAdapterund überschreiben SiegetView(), um den gewünschten Ansichtstyp für jedes Element zurückzugeben. - Ihrer App
SimpleCursorAdapter- Verwenden Sie diesen Adapter, wenn Ihre Daten aus einem
Cursor. Wenn SieSimpleCursorAdapterverwenden, geben Sie ein Layout an, das für jede Zeile imCursorverwendet werden soll, und welche Spalten imCursorin die Ansichten des gewünschten Layouts eingefügt werden sollen. Wenn Sie beispielsweise eine Liste mit Namen und Telefon nummern von Personen erstellen möchten, können Sie eine Abfrage ausführen, die einCursormit einer Zeile für jede Person und Spalten für die Namen und Nummern zurückgibt. Anschließend erstellen Sie ein String-Array, in dem Sie angeben, welche Spalten aus demCursorfür jedes Ergebnis im Layout verwendet werden sollen, und ein Ganzzahl Array, in dem Sie die entsprechenden Ansichten angeben, in denen die einzelnen Spalten platziert werden sollen:Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
Wenn Sie das
SimpleCursorAdapter-Objekt instanziieren, übergeben Sie das Layout, das für jedes Ergebnis verwendet werden soll, dasCursor-Objekt mit den Ergebnissen und diese beiden Arrays:Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
Das
SimpleCursorAdapter-Objekt erstellt dann für jede Zeile imCursor-Objekt eine Ansicht mit dem angegebenen Layout, indem es jedesfromColumns-Element in die entsprechendetoViews-Ansicht einfügt.
Wenn Sie im Laufe der Lebensdauer Ihrer App die zugrunde liegenden Daten ändern, die von Ihrem Adapter gelesen werden, rufen Sie notifyDataSetChanged() auf.
Dadurch wird die angehängte Ansicht benachrichtigt, dass die Daten geändert wurden, und sie wird aktualisiert.
Click-Events verarbeiten
Sie können auf Click-Events für jedes Element in einem AdapterView
reagieren, indem Sie die
AdapterView.OnItemClickListener
Schnittstelle implementieren. Beispiel:
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
Zusätzliche Ressourcen
Informationen zur Verwendung von Layouts in der Sunflower Demo-App auf GitHub


