Android UI, Activities & Navigation

Layouts: LinearLayout & ConstraintLayout

18 min Lesson 1 of 12

Layouts: LinearLayout & ConstraintLayout

In Android, every screen is a hierarchy of View and ViewGroup objects. A View is a single widget — a button, a text label, an image. A ViewGroup is a container that positions its child views according to layout rules. This lesson covers the two layout managers you will reach for most often: LinearLayout for simple stacks, and ConstraintLayout for everything more sophisticated.

How Android Inflates a Layout

Android UI is almost always defined in XML files stored in res/layout/. At runtime, Activity.setContentView(R.layout.activity_main) inflates that XML into real Java objects. The inflation process reads each XML element, instantiates the corresponding class (e.g. android.widget.TextView), applies the XML attributes as method calls, and connects everything into the view tree.

Why XML, not pure Java? Layout XML gives you a clear separation between UI structure and logic, live preview in Android Studio, and access to resource qualifiers (different layouts for phone vs tablet, portrait vs landscape, light vs dark) without touching Java code.

LinearLayout — The Stacking Container

LinearLayout arranges its children in a single line — either a vertical stack or a horizontal row. Every child gets measured in sequence and placed end-to-end. It is the simplest container and the right tool for forms, toolbars, or any interface where elements simply flow in one direction.

The two attributes you set on every LinearLayout:

  • android:orientation="vertical" — children stack top-to-bottom.
  • android:orientation="horizontal" — children sit left-to-right (or right-to-left on RTL locales).

Every view inside a LinearLayout must declare its size with android:layout_width and android:layout_height. The two special values are:

  • match_parent — fill the remaining space offered by the parent.
  • wrap_content — be exactly as large as the content requires.

Here is a vertical LinearLayout with a label and a button:

<!-- res/layout/activity_main.xml --> <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/labelName" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Enter your name:" android:textAppearance="?attr/textAppearanceBodyLarge" /> <EditText android:id="@+id/inputName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Full name" android:inputType="textPersonName" /> <Button android:id="@+id/btnSubmit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="Submit" /> </LinearLayout>

Weight — Distributing Leftover Space

The most powerful LinearLayout attribute is android:layout_weight. After fixed-size children are measured, any remaining space is distributed among children that declare a weight, proportional to their weight values. Set the size in the layout direction to 0dp when using weight so the view takes only its share of remaining space and no more.

<!-- Two buttons split the row 1:2 --> <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="Cancel" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:text="Confirm" /> </LinearLayout>
Avoid deeply nested LinearLayouts. Each level of nesting adds a measurement pass. Three or four nesting levels is a sign you should switch to ConstraintLayout, which achieves complex positioning with a flat, single-level hierarchy.

ConstraintLayout — Flat, Flexible Positioning

ConstraintLayout (from the androidx.constraintlayout library) is the default layout generated by Android Studio. Instead of nesting containers, you attach constraints to each view — rules that connect its edges or centre to the edges of other views or to the parent container. The engine solves all constraints simultaneously and positions every view in a single pass.

Add the dependency in build.gradle (Module):

dependencies { implementation "androidx.constraintlayout:constraintlayout:2.1.4" }

Understanding Constraints

A constraint is always a connection between two anchor points. Every view has six potential anchors: top, bottom, start (left), end (right), and two baselines. Common constraint attributes:

  • app:layout_constraintTop_toTopOf="parent" — align this view's top edge to the parent's top edge.
  • app:layout_constraintStart_toStartOf="parent" — align the start edge to the parent's start.
  • app:layout_constraintTop_toBottomOf="@id/labelName" — place this view's top just below another view's bottom.
  • app:layout_constraintEnd_toEndOf="parent" — pin the end edge to the parent's end.
Every view must have at least one horizontal AND one vertical constraint. A view with only a top constraint and no bottom constraint will compile fine but may jump to position 0,0 at runtime — a common beginner mistake.

Here is the same name-entry form rebuilt with ConstraintLayout:

<!-- res/layout/activity_main.xml --> <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" android:padding="16dp"> <TextView android:id="@+id/labelName" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Enter your name:" android:textAppearance="?attr/textAppearanceBodyLarge" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <EditText android:id="@+id/inputName" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Full name" android:inputType="textPersonName" app:layout_constraintTop_toBottomOf="@id/labelName" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> <Button android:id="@+id/btnSubmit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="Submit" app:layout_constraintTop_toBottomOf="@id/inputName" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>

Notice that layout_width="0dp" on the TextView and EditText means "fill the horizontal constraint" — it stretches from constraintStart_toStartOf="parent" to constraintEnd_toEndOf="parent". This replaces the need for match_parent inside a ConstraintLayout child.

Chains — Distributing Views Along an Axis

A chain is a group of views linked by bidirectional constraints. To form a horizontal chain, connect view A's end to view B's start, and view B's start back to view A's end. Then set app:layout_constraintHorizontal_chainStyle on the first view (the chain head) to control spacing:

  • spread (default) — evenly distribute views and gaps across the available space.
  • spread_inside — pack views to the edges, distribute gaps only between them.
  • packed — cluster all views together; use layout_constraintHorizontal_bias to shift left/right.

Referencing Views in Java

Once a layout is inflated you reference views by their XML android:id using findViewById(). Since Android API 26 / ViewBinding you can skip the cast:

// Inside Activity.onCreate(), after setContentView(...) Button btnSubmit = findViewById(R.id.btnSubmit); EditText inputName = findViewById(R.id.inputName); btnSubmit.setOnClickListener(view -> { String name = inputName.getText().toString().trim(); if (!name.isEmpty()) { // process input } });

Choosing Between the Two

  • Use LinearLayout for forms with one dimension of flow, simple toolbars, and weighted splits between two or three views.
  • Use ConstraintLayout for any screen that has views positioned relative to each other in two dimensions, complex alignment, or responsive behaviour across screen sizes.

In the next lesson you will populate these layouts with the full range of Android's built-in widgets and learn when to reach for each one.