Layout Overview

With the Kotlin language itself covered, we now turn to building actual screens. Every screen TrailLog shows — the trail list, the "add a new hike" form, a single trail's detail view — is, underneath everything, a tree of View objects. This lesson covers that tree structure, the main layout containers you'll reach for, how to size the views inside them, and the density-independent unit Android uses for that sizing. It's the foundation the next several lessons (View Binding, ConstraintLayout, RecyclerView) all build on.

The View / ViewGroup Hierarchy

Every visible thing on an Android screen is a View — a button, a text label, an image. A ViewGroup is a special kind of View that can contain other Views (its children) and arrange them — a ViewGroup is itself still a View, which is what lets these nest arbitrarily deep. A screen's entire layout, then, is just a tree: a root ViewGroup, containing child Views and possibly more nested ViewGroups, each responsible for arranging whatever's inside it.

The Main Layout ViewGroups

ViewGroupWhat it's for
ConstraintLayoutthe modern, recommended default — positions each child relative to other children or to the parent's edges using constraints; covered in depth in ConstraintLayout
LinearLayoutthe simplest option — stacks children in a single row or a single column, in order
FrameLayoutfor stacking views directly on top of each other, or for holding a single child (like one Fragment's content) that fills the available space

Worked Example: TrailLog's Trail-List Screen, at a High Level

Here's a simplified sketch of the actual layout behind TrailLog's trail-list screen: a ConstraintLayout root holding a RecyclerView that fills the screen to show every logged trail, plus a Floating Action Button anchored to the bottom-right corner for adding a new one.

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

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/trailListRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/addTrailFab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Notice the RecyclerView is told to fill all available space while the FloatingActionButton sizes itself to its own content and pins itself to a corner — which is exactly what the next section's sizing keywords control.

Sizing Views: wrap_content, match_parent, and Fixed Values

ValueMeaning
wrap_contentthe view sizes itself just large enough to fit its own content (text, an icon, etc.)
match_parentthe view stretches to fill all the space its parent gives it
a fixed value, e.g. 48dpthe view is exactly that size, regardless of its content or its parent

Why dp, Not Raw Pixels

Android phones and tablets ship with wildly different screen densities — the same number of raw pixels can represent a physically tiny area on a high-density screen and a much larger area on a low-density one. If layouts were sized in raw pixels, a button that looked comfortably tappable on one device could shrink to nearly invisible on another. dp (density-independent pixel) is a unit that Android automatically scales based on the device's actual screen density, so a view declared as 48dp ends up occupying roughly the same physical size — the same number of millimeters on the actual screen — no matter which device it's running on. That's why every measurement in the layout above (16dp margin, and so on) is expressed in dp rather than a plain number.

From XML to Real Views: Inflation

The XML you write is just a description — it isn't the actual UI. At runtime, Android's LayoutInflater reads that XML and "inflates" it: it walks the tree, creating a real View/ViewGroup object in memory for every tag, wiring up the parent-child relationships and attributes exactly as declared, and returns the finished object tree that actually gets drawn to the screen.

Note: The examples in this lesson are correct, real layout XML — but this website's own project doesn't run a live Android Studio build, so you won't see this screen actually render on this page. Try it in your own TrailLog project once you've followed along with the setup lessons earlier in this track.
Next up: Inflation gives you a tree of real View objects — but you still need a way to get typed, null-safe references to them in your Kotlin code. View Binding covers exactly that, and is the modern replacement for findViewById().