Lernen Sie die Grundkonzepte von FrameLayout kennen — der einfachsten ViewGroup im Android SDK, die dazu dient, ein einzelnes Kind-Element (üblicherweise) zu hosten oder mehrere Elemente übereinanderzulegen. FrameLayout eignet sich für Platzhalter-Container, Fragmente, Lade-Indikatoren und Vordergrund-Elemente. Es verwaltet keine Kind-Positionierung — jedes nachfolgende Element wird über dem vorherigen gezeichnet, und seine Position wird durch layout_gravity (left, top, right, bottom, center) bestimmt. Grundlegende Szenarien sind in der FrameLayout-API-Referenz beschrieben.
Wichtige Erkenntnisse
FrameLayout ist die einfachste ViewGroup im Android SDK, die dazu dient, einen Bildschirmbereich zu blockieren und eine einzelne Kind-View (oder mehrere Überlagerungen) anzuzeigen. Im Gegensatz zu LinearLayout (sequentielle Anordnung) und RelativeLayout (relative Positionierung) ändert FrameLayout die Kind-Positionen nicht — jedes neue Kind wird standardmäßig in der oberen linken Ecke (0,0) platziert und über dem vorherigen gezeichnet.
FrameLayout wurde in API Level 1 eingeführt und ist nach wie vor der leichteste Android-Container: Es überschreibt onMeasure nicht mit komplexer Logik und führt eine minimale Anzahl von Layout-Operationen durch. Laut Android Performance Blog führt FrameLayout onLayout in einem einzigen Durchlauf aus und fügt im Vergleich zum direkten Platzieren einer View praktisch keinen Overhead hinzu. Dies macht es zur idealen Wahl für Container, bei denen Geschwindigkeit wichtig ist: RecyclerView-Item-Layouts (in Kombination mit ConstraintLayout für die Positionierung), Fragment-Container, Überlagerungsebenen.
Die Größe von FrameLayout wird standardmäßig durch das größte Kind-Element bestimmt (wenn match_parent nicht gesetzt ist). Wenn kein Kind angegeben ist, kollabiert FrameLayout auf (0,0). Das Attribut android:measureAllChildren (Abschnitt unten) ändert dieses Verhalten.
FrameLayout erbt von ViewGroup und ist der direkte Elternteil vieler spezialisierter Container: FragmentContainerView (Fragmente), CardView (Karten mit Schatten), ScrollView (einzelnes Kind), NestedScrollView. Beim Erstellen einer Activity mit Fragment-Navigation verwendet die Standard-Android-Studio-Vorlage FrameLayout (oder FragmentContainerView) als Root-Container für Fragmente.
android:foreground — ein FrameLayout-Attribut, das ein Drawable angibt, das über allen Kind-Elementen gezeichnet wird. Anders als background (unter den Kindern) wird foreground über dem Inhalt angezeigt und kann transparent sein. Verwendet wird es für: Überlagerungseffekte bei Berührung (Ripple über ?attr/selectableItemBackground), Bildmaskierung, Anzeige von Statusindikatoren (Auswahlhaken über einem Bild).
Foreground unterstützt Standard-Drawable-Ressourcen: ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. Ab API 23+ ist android:foregroundGravity für die Positionierung des Vordergrunds verfügbar (fill, center, top, bottom). Im Füllmodus (fill) wird der Vordergrund über das gesamte FrameLayout gestreckt; im Zentriermodus wird er in der Mitte gezeichnet.
android:measureAllChildren — ein boolesches Attribut (standardmäßig true), das bestimmt, ob alle Kind-Elemente bei der Berechnung der FrameLayout-Größe gemessen werden sollen. Bei true (Standard) berücksichtigt FrameLayout die Größen aller Kinder, einschließlich GONE (mit Größe 0). Bei false misst FrameLayout nur VISIBLE- und INVISIBLE-Kinder — GONE-Elemente werden von der Berechnung ausgeschlossen. Laut Google I/O 2019 beschleunigt das Deaktivieren von measureAllChildren für Container mit vielen GONE-Elementen (z. B. Listen mit umschaltbarer Sichtbarkeit) das anfängliche Zeichnen um 20–60%.
android:layout_gravity — ein Attribut eines FrameLayout-Kindelements (und anderer ViewGroups), das seine Position innerhalb des Containers definiert. In FrameLayout ist layout_gravity die einzige Möglichkeit, die Position eines Kind-Elements zu steuern, da FrameLayout keine eigenen Positionierungsregeln (wie RelativeLayout) oder Richtungen (wie LinearLayout) bereitstellt.
Mögliche Werte: top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. Kombiniert über |: android:layout_gravity="bottom|center_horizontal" — das Element wird am unteren Rand fixiert und horizontal zentriert. Für Elemente, die kleiner als FrameLayout sind, bestimmt layout_gravity ihre Position im freien Raum.
Wenn layout_gravity nicht gesetzt ist, wird das Element standardmäßig in der oberen linken Ecke (top|left) platziert. Bei einem FrameLayout mit mehreren Kindern kann jedes sein eigenes layout_gravity haben — ein Element kann sich in der oberen linken Ecke befinden, ein anderes in der unteren rechten Ecke, ein drittes zentriert. Dies ermöglicht einfache Überlagerungen (z. B. ein Schließen-Symbol über einem Bild).
android:gravity (Elternattribut) richtet den Inhalt innerhalb von FrameLayout aus — zum Beispiel Text innerhalb eines TextView. android:layout_gravity (Kindattribut) richtet das Element selbst innerhalb von FrameLayout aus. Im Kontext von FrameLayout definiert gravity, wie Kinder standardmäßig positioniert werden (ähnlich wie layout_gravity für alle Kinder gleichzeitig), aber das layout_gravity jedes einzelnen Elements überschreibt den Elternwert.
Ein Bild mit einem Textetikett in der unteren rechten Ecke. FrameLayout enthält ein ImageView, das den gesamten Bildschirm ausfüllt, und ein TextView mit layout_gravity="bottom|end" zur Positionierung über dem Bild.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/product_photo"
android:scaleType="centerCrop" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="8dp"
android:background="@drawable/badge_background"
android:elevation="2dp"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp"
android:text="-30%"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</FrameLayout>
ImageView füllt das gesamte FrameLayout (200dp Höhe). Das TextView mit layout_gravity="bottom|end" wird in der unteren rechten Ecke über dem Bild platziert. elevation=2dp fügt einen Schatten unter dem Etikett hinzu und trennt es visuell vom Bild. Dieses minimale Beispiel hätte in LinearLayout einen verschachtelten Container oder benutzerdefinierten Code erfordert.
Ein Bildschirm mit Inhalt und einem zentrierten Fortschrittsbalken, der während des Ladens erscheint. FrameLayout enthält zwei Elemente: Inhalt und ein ProgressBar mit visibility="gone" (im Code umgeschaltet).
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/content_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Geladener Inhalt"
android:textSize="18sp" />
<ProgressBar
android:id="@+id/loading_spinner"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
Die ProgressBar ist standardmäßig ausgeblendet (gone). Wenn der Ladevorgang beginnt, wird findViewById(R.id.loading_spinner).visibility = View.VISIBLE aufgerufen — der Spinner erscheint zentriert über dem Inhalt. Nach dem Laden — .visibility = View.GONE. FrameLayout bietet Überlagerung ohne Verschieben der Inhaltsposition — der Text bewegt sich nicht, wenn der Spinner erscheint, da die ProgressBar darüber gezeichnet wird.
FrameLayout als Standard-Container für FragmentTransaction. Die Aktivität ersetzt Fragmente innerhalb dieses Containers je nach Navigation.
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
import androidx.fragment.app.FragmentTransaction
val fragmentContainer = R.id.fragment_container
fun navigateTo(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(fragmentContainer, fragment)
.addToBackStack(null)
.commit()
}
FrameLayout als Fragment-Container ist der leichteste Weg, Fragment-Navigation zu unterstützen. FragmentContainerView (eine Unterklasse von FrameLayout) wird mit Navigation Component 2.4+ empfohlen, aber ein einfaches FrameLayout bleibt für manuelle FragmentTransactions gültig. Der Hauptvorteil ist, dass FragmentTransaction.replace() den Inhalt vollständig ersetzt, ohne die Aktivität zu beeinträchtigen.
FrameLayout ist optimal für vier Szenarien: Fragment-Container (FragmentContainerView oder FrameLayout), Lade-Überlagerung (ProgressBar über Inhalt), Kartenetiketten (Etikett auf Bild), Platzhalter-Container für ViewStub (lazy loading).
Nicht geeignet für: komplexe Positionierung mehrerer Elemente (ConstraintLayout verwenden), sequenzielle Listen (LinearLayout oder RecyclerView), dynamische Layouts mit wechselnder Elementreihenfolge.
FrameLayout als Wurzelelement des Bildschirms — schlechte Praxis, wenn der Bildschirm mehr als 2–3 Elemente enthält. Für einen Wurzelcontainer verwenden Sie ConstraintLayout — es bietet mehr Kontrolle über die Positionierung ohne Leistungseinbußen. Verwenden Sie FrameLayout nur für Kind-Blöcke, bei denen eine Überlagerung oder ein Platzhalter benötigt wird.
Häufig gestellte Fragen
FrameLayout — ein minimalistischer Container ohne Positionierungssystem (nur layout_gravity), entworfen für die Überlagerung von Elementen. ConstraintLayout — ein vollwertiges Layout-System mit Constraints, Chains, Barrieren, prozentualen Abmessungen und MotionLayout-Unterstützung. FrameLayout ist für einfache Fälle (1 Kind oder Überlagerung) schneller; ConstraintLayout ist für komplexe Layouts erforderlich. Wahl: FrameLayout für Lade-Überlagerung und Fragment-Container; ConstraintLayout für alles andere.
Setzen Sie die Größe von FrameLayout auf wrap_content auf der gewünschten Achse (android:layout_width="wrap_content" und/oder android:layout_height="wrap_content"). FrameLayout passt sich dann der Größe des größten Kind-Elements an. Wenn alle Kinder kleiner als FrameLayout sind, bleibt der überschüssige Platz leer. Für präzise Kontrolle verwenden Sie match_parent mit festem Padding.
Dies ist das beabsichtigte Verhalten von FrameLayout — es verteilt Kinder nicht im Raum, sondern zeichnet sie sequenziell übereinander. Wenn Sie möchten, dass sich Elemente nicht überlappen, verwenden Sie einen anderen Container (LinearLayout, ConstraintLayout). Für teilweise Überlappung mit Kontrolle über die Zeichenreihenfolge verwenden Sie layout_gravity für den Versatz und elevation für die Z-Reihenfolge.
FrameLayout ist schneller für die einfachsten Fälle — ein Kind-Element, ohne komplexe Positionierung. FrameLayout führt onMeasure in minimaler Zeit aus, ohne Constraints zu berechnen. Der Unterschied ist jedoch nur bei Hunderten von Wiederholungen (RecyclerView mit Zehntausenden von Elementen) spürbar. Für einen typischen Bildschirm (1–3 FrameLayouts) beträgt der Unterschied Mikrosekunden und beeinträchtigt die UX nicht. ConstraintLayout ist die universelle Wahl für 95% der Aufgaben.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch