Skip to content
beginner Phase 3 · UI with XML & Views

XML Layouts

Create layouts with LinearLayout, ConstraintLayout, and FrameLayout. Understand nesting and performance.

50m
3 problems
Topic Progress 0%

Why XML Layouts?

Why XML Layouts?

Android separates UI definition from business logic. XML files declare what the screen looks like, and Kotlin/Java code handles behavior. This separation means designers can work on layouts while developers write logic, and the same layout can adapt to different screen configurations without code changes.

The Activity–Layout Relationship

When an Activity starts, it calls setContentView() with a layout resource ID. The Android framework inflates the XML into a hierarchy of View and ViewGroup objects at runtime.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

The generated R.layout.activity_main reference points to res/layout/activity_main.xml.

Anatomy of an XML Layout

Every layout XML file has a root element—typically a ViewGroup—that contains child views:

<?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"
    android:padding="16dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World"
        android:textSize="24sp" />

    <Button
        android:id="@+id/submitBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Submit" />
</LinearLayout>

Every view requires two layout attributes:

  • layout_width — how wide the view should be (match_parent, wrap_content, or a fixed dp value)
  • layout_height — how tall the view should be (same options)

Key Dimensions in Android

Unit Use Case Typical Values
dp Physical dimensions (buttons, margins) 16dp, 24dp, 48dp (touch target)
sp Text size (scales with user font preference) 14sp, 16sp, 24sp
px Avoid — doesn't scale across densities

Always use dp for layout and sp for text. Android runs on devices with wildly different pixel densities; these units ensure consistent physical sizing.

LinearLayout, FrameLayout, and ConstraintLayout

LinearLayout

LinearLayout arranges children in a single direction—either horizontal or vertical. Each child occupies one slot, and you control distribution with layout_weight.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Left" />

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Right" />
</LinearLayout>

Set layout_width="0dp" with layout_weight="1" on each child to split space equally. Weight distributes remaining space after measured sizes, so the first child's weight allocation depends on what space is left.

Common mistake: Setting layout_height="wrap_content" with layout_weight in a vertical LinearLayout. This forces a double measurement pass, which slows down inflation on complex screens.

FrameLayout

FrameLayout stacks children on top of each other. Each child is positioned relative to the parent's edges. This makes FrameLayout ideal for overlays—progress indicators floating on content, badges on icons, or single-child containers that need a background.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:scaleType="centerCrop"
        android:src="@drawable/hero_image" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|start"
        android:layout_margin="12dp"
        android:text="Featured"
        android:background="#80000000"
        android:padding="8dp"
        android:textColor="@android:color/white" />
</FrameLayout>

Use layout_gravity to position a child within the FrameLayout (as opposed to gravity, which positions content inside the view itself).

ConstraintLayout

ConstraintLayout positions views by defining relationships (constraints) between views and the parent. It replaces deeply nested LinearLayout hierarchies with a flat structure, which Android inflates faster.

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/avatar"
        android:layout_width="80dp"
        android:layout_height="80dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_margin="16dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@id/avatar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@id/avatar"
        android:layout_marginStart="12dp"
        android:text="Jane Smith" />
</androidx.constraintlayout.widget.ConstraintLayout>

Every view needs at least one horizontal and one vertical constraint. A missing constraint causes the view to jump to position 0,0 at runtime.

When to Use Which

Layout Best For Watch Out
LinearLayout Simple rows/columns, equal splits Nested weights cause double measurement
FrameLayout Overlays, single-child containers Only one child visible per "layer"
ConstraintLayout Complex flat hierarchies, responsive UI Constraint syntax is verbose

Nesting Pitfalls and Best Practices

Why Nesting Hurts

Every time you nest a ViewGroup inside another ViewGroup, Android performs an extra measurement pass during layout inflation. Two levels of nesting isn't a problem, but five levels of LinearLayout inside LinearLayout inside FrameLayout creates a combinatorial explosion of measure calls.

A layout with depth 5 and three children per level requires 3^5 = 243 measure passes. The same UI built with a flat ConstraintLayout hierarchy requires a single pass.

Flattening with ConstraintLayout

Before ConstraintLayout, you might build a login screen like this:

<!-- BAD: Deep nesting -->
<LinearLayout vertical>
    <FrameLayout>
        <LinearLayout horizontal>
            <LinearLayout vertical>
                <EditText />
                <EditText />
            </LinearLayout>
        </LinearLayout>
    </FrameLayout>
</LinearLayout>

The equivalent ConstraintLayout version eliminates every intermediate container:

<!-- GOOD: Flat hierarchy -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <EditText
        android:id="@+id/email"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:hint="Email" />

    <EditText
        android:id="@+id/password"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/email"
        android:hint="Password"
        android:inputType="textPassword" />
</androidx.constraintlayout.widget.ConstraintLayout>

Layout Inspector

When performance feels sluggish, use Android Studio's Layout Inspector (Tools → Layout Inspector) to see the actual view hierarchy at runtime. It shows:

  • The nesting depth of your views
  • How long each view took to measure and draw
  • The actual runtime layout bounds

Key Best Practices

  1. Keep hierarchy under 10 levels deep — measured in real device time, not just nesting count
  2. Use ViewStub for optional sections — they inflate only when needed, keeping initial load fast
  3. Prefer ConstraintLayout over nested LinearLayouts — flat is always faster
  4. Use merge tags when inflating reusable components — avoids an unnecessary wrapper ViewGroup
  5. Test on low-end devices — a 200ms inflation penalty is invisible on a Pixel 8 but brutal on a $50 device

Quiz

1. What is the primary reason Android uses XML for layouts instead of programmatic view creation?

Question 1 options

2. You have a horizontal LinearLayout with three buttons. Each button has `layout_width="wrap_content"` and `layout_weight="1"`. What happens?

Question 2 options

3. What happens if a view in ConstraintLayout is missing a horizontal constraint?

Question 3 options

4. Which layout tag should you use to avoid adding an extra ViewGroup when inflating a reusable layout component?

Question 4 options

Flashcards

Question

What does `layout_width="0dp"` with `layout_weight="1"` do in a LinearLayout?

Answer

Sets the view to fill remaining space proportionally. Width is computed as the parent's space minus fixed-size siblings, distributed by weight ratio.

Question

What is the difference between `layout_gravity` and `gravity`?

Answer

`layout_gravity` positions a view *within its parent* (e.g., center a button in a FrameLayout). `gravity` positions content *inside* the view itself (e.g., center text inside a TextView).

Question

Why does deep nesting of ViewGroups cause performance issues?

Answer

Each nested ViewGroup triggers an additional measure pass during layout. With branching children, measure calls multiply exponentially, slowing inflation and increasing frame drops during scrolling.

Question

When should you use FrameLayout over LinearLayout?

Answer

FrameLayout when you need to stack views on top of each other (overlays, badges, progress indicators). LinearLayout when you need sequential arrangement in one direction.

Revision Notes

Key Takeaways

  • 1. XML separates UI structure from Kotlin business logic — inflation cost is runtime but architecture benefit is real
  • 2. Use dp for layout dimensions and sp for text sizes to handle screen density differences
  • 3. ConstraintLayout replaces nested LinearLayouts with a flat constraint graph for better performance
  • 4. Missing constraints in ConstraintLayout cause views to jump to position 0,0 at runtime
  • 5. Always measure layout depth with Android Studio's Layout Inspector on real devices

Interview Tips

  • Explain why you would choose ConstraintLayout over nested LinearLayouts — mention measure passes and inflation time
  • Be ready to describe what `layout_weight` actually does (distributes *remaining* space, not proportional)
  • Know the difference between `layout_gravity` and `gravity` — common interview gotcha
  • Discuss ViewStub for optional sections when asked about lazy loading strategies

Cheat Sheet

XML Layouts Cheat Sheet

Every view needs: layout_width and layout_height — set to match_parent, wrap_content, or fixed dp.

Units:

  • dp → physical dimensions (margins, padding, sizes)
  • sp → text sizes (scales with user font preference)

LinearLayout:

  • orientation: horizontal or vertical
  • layout_weight + 0dp width → proportional distribution

FrameLayout:

  • Stacks children; use layout_gravity to position within

ConstraintLayout:

  • Every view needs at least one horizontal + one vertical constraint
  • Missing constraint → view jumps to 0,0 at runtime

Nesting:

  • Deep nesting causes exponential measure passes
  • Flatten with ConstraintLayout
  • Use <merge> to skip wrapper ViewGroups
  • Use <ViewStub> for deferred inflation