FrameLayout: klíčové koncepty, jednoduché pozicování v Androidu

Autor: IT Sectr Publikováno: 2026-02-24 Doba čtení: 8 min

Seznamte se s klíčovými koncepty FrameLayout — nejjednodušší ViewGroup v Android SDK, navržené pro umístění jednoho podřízeného prvku (obvykle) nebo vrstvení několika prvků na sebe. FrameLayout je vhodný pro placeholder kontejnery, fragmenty, indikátory načítání a prvky popředí. Neřídí rozmístění potomků — každý následující prvek se kreslí nad předchozí a jejich pozice je určena layout_gravity (left, top, right, bottom, center). Základní scénáře jsou popsány v FrameLayout API Reference.

Hlavní body

  • Vrstvení — FrameLayout umísťuje prvky postupně jeden na druhý; poslední deklarovaný v XML se kreslí nad všechny.
  • Foreground — atribut android:foreground umožňuje vložit drawable přes všechny podřízené prvky, užitečné pro efekty a maskování.
  • measureAllChildren — ve výchozím nastavení FrameLayout měří všechny potomky, i neviditelné (GONE). Vypnutí zrychluje vykreslování o 20–60%.
  • layout_gravity — jediný způsob pozicování podřízeného prvku uvnitř FrameLayout: top, bottom, left, right, center.
  • Použití s Fragment — FrameLayout je standardní kontejner pro FragmentTransaction.replace(), který nahrazuje obsah bez znovuvytvoření aktivity.

Co je FrameLayout?

FrameLayout je nejjednodušší ViewGroup v Android SDK, navržená pro blokování oblasti obrazovky a zobrazení jednoho podřízeného view (nebo vrstvení několika). Na rozdíl od LinearLayout (sekvenční umístění) a RelativeLayout (relativní pozicování), FrameLayout nemění pozici potomků — každý nový child je ve výchozím nastavení umístěn do levého horního rohu (0,0) a kreslí se nad předchozí.

FrameLayout se objevil v API Level 1 a zůstává nejlehčím Android kontejnerem: nepřepisuje onMeasure složitou logikou a provádí minimální počet layout operací. Podle Android Performance Blog provádí FrameLayout onLayout v jednom průchodu a prakticky nepřidává režii ve srovnání s přímým umístěním View. To z něj činí ideální volbu pro kontejnery, kde záleží na rychlosti: layouty položek RecyclerView (ve spojení s ConstraintLayout pro pozicování), kontejnery fragmentů, překryvné vrstvy.

Výchozí velikost FrameLayout je určena největším podřízeným prvkem (pokud není nastaven match_parent). Pokud není zadán žádný child, FrameLayout se zmenší na (0,0). Atribut android:measureAllChildren (sekce níže) toto chování mění.

FrameLayout v hierarchii Android ViewGroup

FrameLayout dědí z ViewGroup a je přímým rodičem mnoha specializovaných kontejnerů: FragmentContainerView (fragmenty), CardView (karty se stínem), ScrollView (s jedním child), NestedScrollView. Při vytváření Activity s navigací Fragment používá výchozí šablona Android Studio FrameLayout (nebo FragmentContainerView) jako hlavní kontejner pro fragmenty.

Foreground a measureAllChildren

android:foreground — atribut FrameLayout, který určuje drawable kreslený přes všechny podřízené prvky. Na rozdíl od background (pod potomky) se foreground zobrazuje nad obsahem a může být průhledný. Používá se pro: překryvné efekty při stisknutí (ripple přes ?attr/selectableItemBackground), maskování obrázků, zobrazení indikátorů stavu (zaškrtávací značka nad obrázkem).

Foreground podporuje standardní drawable zdroje: ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. Od API 23+ je k dispozici android:foregroundGravity pro pozicování foreground (fill, center, top, bottom). V režimu "vyplnit" (fill) se foreground roztáhne přes celý FrameLayout; v režimu center — kreslí se uprostřed.

android:measureAllChildren — logický atribut (výchozí true), který určuje, zda se mají měřit všechny podřízené prvky při výpočtu velikosti FrameLayout. Pokud je true (výchozí), FrameLayout bere v úvahu velikosti všech potomků, včetně GONE (s velikostí 0). Pokud je false, FrameLayout měří pouze VISIBLE a INVISIBLE potomky — prvky GONE jsou z výpočtu vyloučeny. Podle Google I/O 2019 vypnutí measureAllChildren u kontejnerů s velkým počtem prvků GONE (např. seznamy s přepínáním viditelnosti) zrychluje počáteční vykreslování o 20–60%.

layout_gravity: pozicování uvnitř FrameLayout

android:layout_gravity — atribut podřízeného prvku FrameLayout (a dalších ViewGroup), který určuje jeho pozici uvnitř kontejneru. Ve FrameLayout je layout_gravity jediným způsobem řízení polohy podřízeného prvku, protože FrameLayout neposkytuje vlastní pravidla pozicování (jako RelativeLayout) ani směr (jako LinearLayout).

Možné hodnoty: top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. Kombinují se pomocí |: android:layout_gravity="bottom|center_horizontal" — prvek je přitisknut k dolnímu okraji a horizontálně vycentrován. U prvků, jejichž velikost je menší než FrameLayout, určuje layout_gravity jejich pozici ve volném prostoru.

Pokud layout_gravity není nastaven, je prvek ve výchozím nastavení umístěn do levého horního rohu (top|left). U FrameLayout obsahujícího několik potomků může mít každý svůj vlastní layout_gravity — jeden prvek může být v levém horním rohu, druhý v pravém dolním rohu, třetí uprostřed. To umožňuje vytvářet jednoduché překryvy (např. křížek pro zavření nad obrázkem).

Rozdíl mezi gravity a layout_gravity

android:gravity (rodičovský atribut) zarovnává obsah uvnitř FrameLayout — například text uvnitř TextView. android:layout_gravity (podřízený atribut) zarovnává samotný prvek uvnitř FrameLayout. V kontextu FrameLayout gravity určuje, jak jsou potomci ve výchozím nastavení uspořádáni (analogie layout_gravity pro všechny potomky najednou), ale layout_gravity každého konkrétního prvku přepisuje rodičovskou hodnotu.

Příklady: XML a případy použití

Příklad 1: Základní překryv — štítek na obrázku

Obrázek a textový štítek v pravém dolním rohu. FrameLayout obsahuje ImageView přes celou obrazovku a TextView s layout_gravity="bottom|end" pro pozicování navrchu.

xml
<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 zabírá celý FrameLayout (200dp na výšku). TextView s layout_gravity="bottom|end" je umístěn v pravém dolním rohu nad obrázkem. elevation=2dp přidává stín pod štítek a vizuálně jej odděluje od obrázku. Toto je minimální příklad, který by v LinearLayout vyžadoval vnořený kontejner nebo vlastní kód.

Příklad 2: Indikátor načítání (progress bar nad obsahem)

Obrazovka s obsahem a progress barem uprostřed, který se zobrazí při načítání. FrameLayout obsahuje dva prvky: obsah a ProgressBar s visibility="gone" (přepíná se v kódu).

xml
<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="Načtený obsah"
        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>

ProgressBar je ve výchozím nastavení skrytý (gone). Při spuštění načítání se v kódu zavolá findViewById(R.id.loading_spinner).visibility = View.VISIBLE — spinner se objeví uprostřed nad obsahem. Po načtení — .visibility = View.GONE. FrameLayout zajišťuje překryv bez změny pozice obsahu — text se při objevení spinneru neposouvá, protože ProgressBar se kreslí navrchu.

Příklad 3: Kontejner fragmentů

FrameLayout jako standardní kontejner pro FragmentTransaction. Aktivita v závislosti na navigaci nahrazuje fragmenty uvnitř tohoto kontejneru.

xml
<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
kotlin
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 jako kontejner fragmentů — nejlehčí způsob podpory Fragment Navigation. FragmentContainerView (dědic FrameLayout) je doporučen s Navigation Component 2.4+, ale jednoduchý FrameLayout zůstává platný pro ruční FragmentTransaction. Klíčová výhoda — FragmentTransaction.replace() zcela nahrazuje obsah, aniž by ovlivnil Activity.

Kdy použít FrameLayout

FrameLayout je optimální pro čtyři scénáře: kontejner fragmentů (FragmentContainerView nebo FrameLayout), překryv načítání (ProgressBar nad obsahem), štítky na kartách (značka na obrázku), placeholder kontejner pro ViewStub (líné načítání).

Není vhodný pro: složité pozicování více prvků (použijte ConstraintLayout), sekvenční seznamy (LinearLayout nebo RecyclerView), dynamické rozvržení se změnou pořadí prvků.

FrameLayout jako kořenový prvek obrazovky — špatná praxe, pokud obrazovka obsahuje více než 2–3 prvky. Pro kořenový kontejner použijte ConstraintLayout — poskytuje větší kontrolu nad pozicováním bez ztráty výkonu. FrameLayout používejte pouze pro podřízené bloky, kde je potřeba překryv nebo placeholder.

Často kladené otázky

Jaký je rozdíl mezi FrameLayout a ConstraintLayout?

FrameLayout — minimalistický kontejner bez systému pozicování (pouze layout_gravity), určený pro vrstvení prvků. ConstraintLayout — plnohodnotný layout systém s omezeními, řetězci, bariérami, procentuálními velikostmi a podporou MotionLayout. FrameLayout je rychlejší pro jednoduché případy (1 child nebo overlay); ConstraintLayout je povinný pro složitá rozvržení. Volba: FrameLayout pro překryv načítání a kontejner fragmentů; ConstraintLayout pro všechno ostatní.

Jak zařídit, aby FrameLayout zabíral pouze místo největšího child?

Nastavte velikost FrameLayout na wrap_content na požadované ose (android:layout_width="wrap_content" a/nebo android:layout_height="wrap_content"). V tomto případě se FrameLayout přizpůsobí velikosti největšího podřízeného prvku. Pokud jsou všechny potomky menší než FrameLayout, přebytečné místo zůstane prázdné. Pro přesné řízení použijte match_parent s pevným paddingem.

Proč se prvky ve FrameLayout překrývají?

To je normální chování FrameLayout — nerozděluje potomky v prostoru, ale kreslí je postupně jeden na druhý. Pokud nechcete, aby se prvky překrývaly, použijte jiný kontejner (LinearLayout, ConstraintLayout). Pro částečné překrytí s kontrolou pořadí kreslení použijte layout_gravity pro posun a elevation pro Z-order.

Co je rychlejší: FrameLayout nebo ConstraintLayout?

FrameLayout je rychlejší pro maximálně jednoduché případy — jeden podřízený prvek, bez složitého pozicování. FrameLayout provádí onMeasure v minimálním čase, bez výpočtu omezení. Rozdíl je však patrný pouze při stovkách opakování (RecyclerView s desítkami tisíc prvků). Pro běžnou obrazovku (1–3 FrameLayout) je rozdíl v mikrosekundách a neovlivňuje UX. ConstraintLayout je univerzální volbou pro 95% úkolů.

Shrnutí

  • FrameLayout — nejjednodušší Android ViewGroup pro vrstvení prvků a placeholder kontejnery s minimální režií.
  • Vrstvení — každý nový child se kreslí nad předchozí; poslední deklarovaný v XML je nejvyšší.
  • Foreground — drawable nad všemi potomky pro překryvné efekty, maskování a ripple animaci.
  • measureAllChildren — vypnutí (false) vylučuje prvky GONE z výpočtu velikosti, zrychluje vykreslování o 20–60%.
  • layout_gravity — jediný mechanismus pozicování: top, bottom, left, right, center a jejich kombinace.
  • Kontejner fragmentů — nejčastější případ použití: FrameLayout (nebo FragmentContainerView) pro FragmentTransaction.replace().
  • Výkon — nejrychlejší kontejner pro 1 child; pro složitá rozvržení zaostává za ConstraintLayout.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také