Vi förklarar essensen av RelativeLayout — ViewGroup i Android SDK för att positionera underordnade element relativt varandra eller relativt den överordnade behållaren. Till skillnad från LinearLayout, som arrangerar element strikt sekventiellt, gör RelativeLayout det möjligt att placera ett element till vänster, höger, ovanför, nedanför eller i mitten relativt ett annat element baserat på dess ID. Detta gör RelativeLayout praktiskt för överlappande och komplexa layouter utan nästling. De grundläggande reglerna beskrivs i dokumentationen för Android Developers.
Huvudpunkter
RelativeLayout — ViewGroup som dök upp i Android SDK från API Level 1, som positionerar underordnade element genom deklarativa regler (layout rules) relativt föräldern eller andra underordnade element. Varje regel definieras av ett XML-attribut som android:layout_above, android:layout_below, android:layout_toLeftOf med värdet av målelementets ID.
Före RelativeLayouts tillkomst var utvecklare tvungna att använda nästlade LinearLayouts för varje icke-standardpositionering — detta ledde till djup nästling och långsam rendering. RelativeLayout löste detta problem genom att erbjuda relativ positionering på en hierarkisk nivå. Dess flexibilitet är dock begränsad jämfört med moderna ConstraintLayout: RelativeLayout stöder inte kedjor, barriärer, guidelinjer och procentuella storlekar.
RelativeLayout har två nyckelfunktioner: en onMeasure-passning (till skillnad från LinearLayout med weight som kräver två passningar) och beroende av deklarationsordning — om element A refererar till element B och B deklareras efter A, måste B ha en känd storlek vid mätning av A. Enligt Android Developers Guide (2024) utför RelativeLayout mätning i en passning om alla regler refererar till redan uppmätta element. Annars krävs en andra passning, vilket minskar prestandan.
RelativeLayout är motiverat för enkla layouter med 3–7 element där relativ positionering krävs (etikett ovanför knapp, ikon till höger om text, panel längst ner på skärmen). För nya projekt rekommenderas ConstraintLayout, men RelativeLayout används fortfarande brett i äldre kod och bibliotek.
RelativeLayout använder två typer av regler: relative-regler (positionering i förhållande till ett annat element) och align-regler (förankring till föräldern). Varje underordnat element kan ha ett obegränsat antal regler, men motstridiga regler (t.ex. alignParentTop och below av ett annat element) löses till förmån för den senast deklarerade i attributet.
Relative-regler:
- android:layout_above="@id/target" — elementets nedre kant är förankrad vid targetets övre kant.
- android:layout_below="@id/target" — elementets övre kant är förankrad vid targetets nedre kant.
- android:layout_toLeftOf="@id/target" — högerkanten är förankrad vid targetets vänstra kant.
- android:layout_toRightOf="@id/target" — vänsterkanten är förankrad vid targetets högra kant.
- android:layout_toStartOf="@id/target" — motsvarighet till toLeftOf för RTL-lokaliseringar.
- android:layout_toEndOf="@id/target" — motsvarighet till toRightOf för RTL.
Align-regler (till förälder):
- android:layout_alignParentTop="true" — elementets övre kant sammanfaller med förälderns övre kant.
- android:layout_alignParentBottom="true" — den nedre kanten sammanfaller med förälderns nedre kant.
- android:layout_alignParentLeft="true" — vänsterkanten sammanfaller med förälderns vänstra kant.
- android:layout_alignParentRight="true" — högerkanten sammanfaller med förälderns högra kant.
- android:layout_alignParentStart och android:layout_alignParentEnd — för RTL.
Align-regler till andra element:
- android:layout_alignTop="@id/target" — elementets topp sammanfaller med targetets topp.
- android:layout_alignBottom, android:layout_alignLeft, android:layout_alignRight, android:layout_alignStart, android:layout_alignEnd — liknande.
- android:layout_alignBaseline="@id/target" — justering efter textens baslinje (användbart för rader med olika teckenstorlekar).
Centrering i RelativeLayout definieras av tre attribut: android:layout_centerInParent="true" (mitten av föräldern på båda axlarna), android:layout_centerHorizontal="true" (centrerad horisontellt) och android:layout_centerVertical="true" (centrerad vertikalt). Centrering är kompatibel med andra regler: ett element kan centreras horisontellt och samtidigt förankras vid förälderns nedre kant.
Ordning för överlappning (Z-order) i RelativeLayout bestäms av deklarationsordningen för element i XML. Det först deklarerade elementet ritas först (kommer att vara längst ner), det sista — sist (kommer att vara överst). Om du behöver ändra överlappningsordningen utan att ändra XML, använd android:elevation (från API 21) — element med högre elevation ritas ovanpå. För versioner under API 21 regleras överlappningsordningen endast av deklarationsordningen.
Viktigt: RelativeLayout stöder inte attributet android:elevation för föräldern — varje element hanterar sin egen elevation självständigt. Vid konflikt mellan positioneringsregler och elevation (t.ex. överlappande element) har elevation prioritet vid ritning, men inte vid positionering — ett element med högre elevation kan visuellt täcka ett annat, även om dess layoutregler placerar det bakom.
Avatar centrerad högst upp, namn under avatar, status under namn, åtgärdsknappen längst ner på skärmen. Alla element använder relative-regler för sekventiell förankring.
<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="Redigera profil" />
</RelativeLayout>
Avatar är förankrad upptill via marginTop + centerHorizontal, namn — under avatar via layout_below, status — under namn, knapp — vid förälderns nedre kant via alignParentBottom. Alla element är oberoende av varandra, det finns inga kedjor eller nästling.
Ikon med ett rött märke (cirkel med nummer) i det övre högra hörnet. Märket positioneras i förhållande till ikonen via align till dess kanter med negativa marginaler för överlappning.
<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>
Märket är förankrat vid ikonens övre och högra kant. Negativa marginaler (-6dp) flyttar märket utåt och skapar en effekt av att överskrida ikonens gräns. Detta är ett populärt mönster för aviseringar som utan RelativeLayout skulle kräva FrameLayout eller anpassad ritning.
Inloggningsformulär: logotyp centrerad högst upp, e-postfält under den, lösenordsfält under e-post, knappen 'Logga in' under lösenord, länken 'Registrera' fast längst ner. Alla element är sekventiellt förankrade 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="Lösenord"
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="Logga in" />
<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="Inget konto? Registrera"
android:textColor="@color/primary" />
</RelativeLayout>
Skärmen använder 5 element på en hierarkisk nivå. Flödet uppifrån och ner (logotyp → e-post → lösenord → knapp) tillhandahålls av layout_below, och länken är fast längst ner via alignParentBottom. För samma funktionalitet skulle LinearLayout kräva två nästlade behållare (en för den övre gruppen, den andra för länken med weight).
Jämförelse av två ViewGroups för relativ positionering: RelativeLayout (klassisk, API 1+) och ConstraintLayout (modern, Jetpack). Kriterier: flexibilitet, prestanda, RTL-stöd och anpassningsförmåga.
| Egenskap | RelativeLayout | ConstraintLayout |
|---|---|---|
| Procentuella storlekar | Nej (endast fasta och match_parent) | Ja (width_percent, height_percent, guideline_percent) |
| RTL-stöd | Via start/end (API 17+) | Inbyggt |
| Chain / kedjor | Nej | Ja (spread, spread_inside, packed) |
| Barrier / Group / Flow | Nej | Ja (virtuella hjälpare) |
| MotionLayout-animationer | Nej | Ja |
| onMeasure-passningar | 1 (utan beroendecykler) | 2 (alltid, men optimerade) |
| Centrering | centerInParent, centerHorizontal, centerVertical | Via bias (0.0–1.0) med motsatta begränsningar |
| När ska användas | Äldre kod, enkla layouter med 3–7 element | Nya projekt, komplexa skärmar, adaptiva layouter |
RelativeLayout är sämre än ConstraintLayout på nästan alla sätt, förutom en: det är inbyggt i Android SDK från API 1 och kräver inga extra beroenden. För projekt som fortfarande använder minSdk under API 14 (Android 4.0) är RelativeLayout det enda standardalternativet för relativ positionering. I alla andra fall rekommenderar Google ConstraintLayout.
Vanliga frågor
Den mest sannolika orsaken — brist på tillräckligt antal positioneringsregler. Varje element i RelativeLayout måste ha minst en horisontell regel (alignParentLeft, toRightOf, centerHorizontal) och en vertikal regel (alignParentTop, below, centerVertical). Om det inte finns några regler hamnar elementet i position (0,0) och kan vara dolt under andra element eller utanför skärmen. Den andra orsaken — ett cykliskt beroende (element A är förankrat vid B, B är förankrat vid A), vilket leder till oförutsägbart beteende.
Använd attributet android:layout_centerInParent="true". Det centrerar elementet på båda axlarna samtidigt. Om du bara behöver horisontellt — android:layout_centerHorizontal="true", bara vertikalt — android:layout_centerVertical="true". Centrering fungerar tillsammans med marginal — elementet förskjuts i förhållande till mitten med det angivna avståndet.
Det går, men rekommenderas inte. RelativeLayout utför två onMeasure-passningar vid cykliska beroenden, vilket är 15–30 % långsammare än ConstraintLayout i RecyclerView-listor. För objektlayouter i RecyclerView, använd ConstraintLayout — det ger en platt hierarki med minimal mättid. Om RelativeLayout redan används i ett äldre projekt, se till att elementen inte skapar cykliska beroenden och mät rullnings-FPS via Profile GPU Rendering.
android:layout_margin anger marginaler från alla sidor samtidigt. android:layout_marginTop — endast från toppen. Det mer specifika attributet har prioritet: om både layout_margin (16dp) och layout_marginTop (8dp) är inställda blir toppmarginalen 8dp. I RelativeLayout fungerar marginalen i förhållande till begränsningen, inte i förhållande till intilliggande element: layout_marginTop med layout_below="@id/target" — detta är avståndet från elementets övre kant till targetets nedre kant.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också