We leggen de essentie van RelativeLayout uit — ViewGroup in Android SDK voor het positioneren van onderliggende elementen ten opzichte van elkaar of ten opzichte van de bovenliggende container. In tegenstelling tot LinearLayout, dat elementen strikt opeenvolgend rangschikt, maakt RelativeLayout het mogelijk om elk element links, rechts, boven, onder of in het midden van een ander element te plaatsen op basis van zijn ID. Dit maakt RelativeLayout handig voor overlappende en complexe lay-outs zonder nesting. De basisregels worden beschreven in de documentatie van Android Developers.
Belangrijkste punten
RelativeLayout — ViewGroup, verschenen in Android SDK vanaf API Level 1, die onderliggende elementen positioneert via declaratieve regels (layout rules) ten opzichte van de ouder of andere onderliggende elementen. Elke regel wordt gedefinieerd door een XML-attribuut zoals android:layout_above, android:layout_below, android:layout_toLeftOf met de waarde van de ID van het doelwit.
Vóór de komst van RelativeLayout waren ontwikkelaars gedwongen om geneste LinearLayouts te gebruiken voor elke niet-standaard positionering — dit leidde tot diepe nesting en langzame weergave. RelativeLayout loste dit probleem op door relatieve positionering op één hiërarchisch niveau aan te bieden. De flexibiliteit is echter beperkt in vergelijking met moderne ConstraintLayout: RelativeLayout ondersteunt geen kettingen, barrières, hulplijnen en procentuele afmetingen.
RelativeLayout heeft twee belangrijke kenmerken: één onMeasure-pass (in tegenstelling tot LinearLayout met weight, dat twee passes vereist) en afhankelijkheid van declaratievolgorde — als element A verwijst naar element B en B is gedeclareerd na A, moet B een bekende grootte hebben op het moment van meting van A. Volgens Android Developers Guide (2024) voert RelativeLayout meting uit in één pass als alle regels verwijzen naar reeds gemeten elementen. Anders is een tweede pass nodig, wat de prestaties vermindert.
RelativeLayout is gerechtvaardigd voor eenvoudige lay-outs met 3–7 elementen waar relatieve positionering vereist is (label boven knop, pictogram rechts van tekst, paneel onderaan het scherm). Voor nieuwe projecten wordt ConstraintLayout aanbevolen, maar RelativeLayout wordt nog steeds veel gebruikt in legacy-code en bibliotheken.
RelativeLayout gebruikt twee soorten regels: relative-regels (positionering ten opzichte van een ander element) en align-regels (verankering aan de ouder). Elk onderliggend element kan een onbeperkt aantal regels hebben, maar conflicterende regels (bijv. alignParentTop en below van een ander element) worden opgelost in het voordeel van de laatst gedeclareerde in het attribuut.
Relative-regels:
- android:layout_above="@id/target" — de onderrand van het element is verankerd aan de bovenrand van target.
- android:layout_below="@id/target" — de bovenrand van het element is verankerd aan de onderrand van target.
- android:layout_toLeftOf="@id/target" — de rechterrand is verankerd aan de linkerrand van target.
- android:layout_toRightOf="@id/target" — de linkerrand is verankerd aan de rechterrand van target.
- android:layout_toStartOf="@id/target" — analoog aan toLeftOf voor RTL-lokalisaties.
- android:layout_toEndOf="@id/target" — analoog aan toRightOf voor RTL.
Align-regels (aan ouder):
- android:layout_alignParentTop="true" — de bovenrand van het element valt samen met de bovenrand van de ouder.
- android:layout_alignParentBottom="true" — de onderrand valt samen met de onderrand van de ouder.
- android:layout_alignParentLeft="true" — de linkerrand valt samen met de linkerrand van de ouder.
- android:layout_alignParentRight="true" — de rechterrand valt samen met de rechterrand van de ouder.
- android:layout_alignParentStart en android:layout_alignParentEnd — voor RTL.
Align-regels aan andere elementen:
- android:layout_alignTop="@id/target" — de bovenkant van het element valt samen met de bovenkant van target.
- android:layout_alignBottom, android:layout_alignLeft, android:layout_alignRight, android:layout_alignStart, android:layout_alignEnd — op dezelfde manier.
- android:layout_alignBaseline="@id/target" — uitlijning op de basislijn van tekst (nuttig voor rijen met verschillende lettergroottes).
Centreren in RelativeLayout wordt gedefinieerd door drie attributen: android:layout_centerInParent="true" (midden van de ouder op beide assen), android:layout_centerHorizontal="true" (horizontaal gecentreerd) en android:layout_centerVertical="true" (verticaal gecentreerd). Centreren is compatibel met andere regels: een element kan horizontaal worden gecentreerd en tegelijkertijd aan de onderrand van de ouder worden verankerd.
Volgorde van overlapping (Z-order) in RelativeLayout wordt bepaald door de declaratievolgorde van elementen in XML. Het eerst gedeclareerde element wordt als eerste getekend (komt onderaan), het laatste — als laatste (komt bovenaan). Als u de volgorde van overlapping wilt wijzigen zonder XML te wijzigen, gebruik dan android:elevation (vanaf API 21) — elementen met hogere elevation worden bovenop getekend. Voor versies onder API 21 wordt de volgorde van overlapping alleen geregeld door de declaratievolgorde.
Belangrijk: RelativeLayout ondersteunt het attribuut android:elevation niet voor de ouder — elk element beheert zijn eigen elevation zelfstandig. Bij een conflict tussen positioneringsregels en elevation (bijv. overlappende elementen) heeft elevation prioriteit bij het tekenen, maar niet bij het positioneren — een element met hogere elevation kan een ander visueel bedekken, zelfs als zijn layout-regels het erachter plaatsen.
Avatar gecentreerd bovenaan, naam onder avatar, status onder naam, actieknop onderaan het scherm. Alle elementen gebruiken relative-regels voor opeenvolgende verankering.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/avatar"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:src="@drawable/avatar_placeholder" />
<TextView
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/avatar"
android:layout_centerHorizontal="true"
android:layout_marginTop="12dp"
android:text="Ivan Ivanov"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/user_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/user_name"
android:layout_centerHorizontal="true"
android:text="Online"
android:textColor="@color/green" />
<Button
android:id="@+id/edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="24dp"
android:text="Profiel bewerken" />
</RelativeLayout>
Avatar is bovenaan verankerd via marginTop + centerHorizontal, naam — onder avatar via layout_below, status — onder naam, knop — aan de onderrand van de ouder via alignParentBottom. Alle elementen zijn onafhankelijk van elkaar, er zijn geen kettingen of nesting.
Pictogram met een rode badge (cirkel met nummer) in de rechterbovenhoek. De badge wordt gepositioneerd ten opzichte van het pictogram via align aan de randen met negatieve margins voor overlapping.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_notification" />
<TextView
android:id="@+id/badge"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignTop="@+id/icon"
android:layout_alignRight="@+id/icon"
android:layout_marginTop="-6dp"
android:layout_marginRight="-6dp"
android:gravity="center"
android:background="@drawable/badge_background"
android:text="3"
android:textColor="@android:color/white"
android:textSize="10sp" />
</RelativeLayout>
De badge is verankerd aan de boven- en rechterrand van het pictogram. Negatieve margins (-6dp) verplaatsen de badge naar buiten, waardoor een effect van overlapping van de pictogramrand ontstaat. Dit is een populair patroon voor meldingen dat zonder RelativeLayout een FrameLayout of aangepaste weergave zou vereisen.
Inlogformulier: logo gecentreerd bovenaan, e-mailveld eronder, wachtwoordveld onder e-mail, knop 'Inloggen' onder wachtwoord, link 'Registreren' onderaan vastgezet. Alle elementen zijn opeenvolgend verankerd via layout_below.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<TextView
android:id="@+id/logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="48dp"
android:text="MyApp"
android:textSize="32sp"
android:textStyle="bold" />
<EditText
android:id="@+id/email_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/logo"
android:layout_marginTop="32dp"
android:hint="Email" />
<EditText
android:id="@+id/password_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/email_input"
android:layout_marginTop="16dp"
android:hint="Wachtwoord"
android:inputType="textPassword" />
<Button
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/password_input"
android:layout_marginTop="24dp"
android:text="Inloggen" />
<TextView
android:id="@+id/register_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="16dp"
android:text="Geen account? Registreren"
android:textColor="@color/primary" />
</RelativeLayout>
Het scherm gebruikt 5 elementen op één hiërarchisch niveau. De stroom van boven naar beneden (logo → e-mail → wachtwoord → knop) wordt verzorgd door layout_below, en de link is onderaan vastgezet via alignParentBottom. Voor dezelfde functionaliteit zou LinearLayout twee geneste containers nodig hebben (één voor de bovenste groep, de tweede voor de link met weight).
Vergelijking van twee ViewGroups voor relatieve positionering: RelativeLayout (klassiek, API 1+) en ConstraintLayout (modern, Jetpack). Criteria: flexibiliteit, prestaties, RTL-ondersteuning en aanpasbaarheid.
| Kenmerk | RelativeLayout | ConstraintLayout |
|---|---|---|
| Procentuele afmetingen | Nee (alleen vast en match_parent) | Ja (width_percent, height_percent, guideline_percent) |
| RTL-ondersteuning | Via start/end (API 17+) | Ingebouwd |
| Chain / kettingen | Nee | Ja (spread, spread_inside, packed) |
| Barrier / Group / Flow | Nee | Ja (virtuele helpers) |
| MotionLayout-animaties | Nee | Ja |
| onMeasure-passes | 1 (zonder afhankelijkheidscycli) | 2 (altijd, maar geoptimaliseerd) |
| Centreren | centerInParent, centerHorizontal, centerVertical | Via bias (0.0–1.0) met tegenovergestelde constraints |
| Wanneer gebruiken | Legacy-code, eenvoudige lay-outs met 3–7 elementen | Nieuwe projecten, complexe schermen, adaptieve lay-outs |
RelativeLayout is op bijna alle punten inferieur aan ConstraintLayout, behalve één: het is ingebouwd in Android SDK vanaf API 1 en vereist geen extra afhankelijkheden. Voor projecten die nog minSdk onder API 14 (Android 4.0) gebruiken, is RelativeLayout de enige standaardoptie voor relatieve positionering. In alle andere gevallen beveelt Google ConstraintLayout aan.
Veelgestelde vragen
De meest waarschijnlijke oorzaak — onvoldoende positioneringsregels. Elk element in RelativeLayout moet ten minste één horizontale regel (alignParentLeft, toRightOf, centerHorizontal) en één verticale regel (alignParentTop, below, centerVertical) hebben. Als er geen regels zijn, komt het element op positie (0,0) terecht en kan het verborgen zijn onder andere elementen of buiten het scherm. De tweede oorzaak — een cyclische afhankelijkheid (element A is aan B verankerd, B aan A), wat leidt tot onvoorspelbaar gedrag.
Gebruik het attribuut android:layout_centerInParent="true". Het centreert het element op beide assen tegelijk. Als u alleen horizontaal nodig heeft — android:layout_centerHorizontal="true", alleen verticaal — android:layout_centerVertical="true". Centreren werkt samen met margin — het element wordt verschoven ten opzichte van het midden met de opgegeven afstand.
Het kan, maar wordt niet aanbevolen. RelativeLayout voert twee onMeasure-passes uit bij cyclische afhankelijkheden, wat 15–30% langzamer is dan ConstraintLayout in RecyclerView-lijsten. Gebruik voor item-lay-outs in RecyclerView ConstraintLayout — het biedt een platte hiërarchie met minimale meettijd. Als RelativeLayout al wordt gebruikt in een legacy-project, zorg er dan voor dat de elementen geen cyclische afhankelijkheden creëren en meet de scroll-FPS via Profile GPU Rendering.
android:layout_margin stelt marges aan alle zijden tegelijk in. android:layout_marginTop — alleen aan de bovenkant. Het specifiekere attribuut heeft prioriteit: als zowel layout_margin (16dp) als layout_marginTop (8dp) zijn ingesteld, is de bovenmarge 8dp. In RelativeLayout werkt de marge ten opzichte van de constraint, niet ten opzichte van het aangrenzende element: layout_marginTop met layout_below="@id/target" — dit is de afstand van de bovenrand van het element tot de onderrand van target.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook