Mehdi Tmimi Mobile

Mobile Development Lab 1 Part 3 of 8

Place the views with ConstraintLayout

Without a vertical constraint, the card jumps to the phone’s top.

The phone at the end of Part 2: “Hello, Notes!” in the middle, with no bar.
Where you start
The phone at the end of this part: the orange band with the robot and Notes 0, the white card with two fields, 0 / 140, Clear and Add, then YOUR NOTES and its hint.
Where you arrive
  1. 3.2 the band and the logo
  2. 3.3 the title and the card
  3. 3.5 the count, the card’s last row, the list

Before you start

By the end you can

  • drag views and give them ids;
  • tie a view to the parent or to another view; use 0dp;
  • explain why a view without constraints jumps; preview other sizes.
  • Layout Design · Code · Split
  • Emulator

Red or yellow marks: advice, not build errors.

Behind, or a fresh project? Start from here about 4 min
  1. The project: your own from Part 2, or a fresh one: Part 0, steps 0.3 and 0.4 (about 5 minutes).

  2. Your package name, for the code of this page:

    Without JavaScript, the code says com.yourname.notes: replace yourname by the name you chose.

  3. Gradle: check these 3 lines. Add any that is missing, then click Sync Now. Keep your own version numbers.

    Gradle Scripts › libs.versions.tomlAdd the marked lines
    [versions]agp = "9.5.0"junit = "4.13.2"junitVersion = "1.3.0"espressoCore = "3.7.0"appcompat = "1.8.0"material = "1.14.0"constraintlayout = "2.2.2"
    [libraries]junit = { group = "junit", name = "junit", version.ref = "junit" }ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }material = { group = "com.google.android.material", name = "material", version.ref = "material" }constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
    [plugins]android-application = { id = "com.android.application", version.ref = "agp" }
    Gradle Scripts › build.gradle.kts (Module :app)Add the marked lines
    plugins {    alias(libs.plugins.android.application)}
    android { namespace = "com.yourname.notes" compileSdk { version = release(37) }
    defaultConfig { applicationId = "com.yourname.notes" minSdk = 24 targetSdk = 37 versionCode = 1 versionName = "1.0"
    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" }
    buildTypes { release { optimization { enable = true packageScope = setOf("androidx.**", "kotlin.**", "kotlinx.**") } } } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 }}
    dependencies { implementation(libs.appcompat) implementation(libs.material) implementation(libs.constraintlayout) testImplementation(libs.junit) androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.ext.junit)}
  4. res and manifest: download the pack and open it in Explorer. Drag its app folder onto your project folder (C:\Users\<you>\AndroidStudioProjects\Notes), then choose Replace the files in the destination. Not Extract All: it makes a folder inside and replaces nothing. Then, in res › values › themes, delete themes.xml (night) if it is still there.

    lab1-part3-res.zip zip · 2.1 KB
  5. Java: open MainActivity.java, select all, then paste this file. Missing? First right-click kotlin+java › com.yourname.notes, the one without (test), then NewJava Class: type MainActivity, then press Enter.

    kotlin+java › com.yourname.notes › MainActivity.javaReplace the whole file
    package com.yourname.notes;
    import android.os.Bundle;
    import androidx.appcompat.app.AppCompatActivity;
    public class MainActivity extends AppCompatActivity {
    @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
  6. ▶. You are ready when the phone shows “Hello, Notes!” with no bar.

Step 1 of 6

Open the layout editor

6 min

Goal Find the editor’s tools, then empty the screen.

  • Layout res › layout › activity_main.xml · Design
  1. The layout file, in Design.

    1. In the Project window, double-click res › layout › activity_main.xml.
    2. It opens in Design: Palette top left, Component Tree under it, Attributes on the right.
    Layout editor The whole windowFull size
    The whole window with activity_main.xml in Design mode: Palette and Component Tree on the left of the editor, the preview with Hello, Notes! in the middle, Attributes on the right, and the Code, Split and Design buttons at the top right.
    1. Code · Split · Design: the editor opens in Design.
    2. Component Tree: the views, nested. A view is one element of the screen: a text, a field, a button, a container.
    3. Palette: the views to drag.
    4. Attributes: the selected view’s attributes.
  2. The XML behind it.

    1. At the top right of the editor, click Code.
    res › layout › activity_main.xmlRead only
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <TextView android:id="@+id/textHello" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, Notes!" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    1. The root, a ConstraintLayout. android: marks Android’s own attributes.
    2. app: marks a library’s attributes: here ConstraintLayout’s, added in Part 1.
    3. tools: is for the editor only: tools:context, and the tools:layout_editor_… lines a drag may write. The app never sees them.
    4. Keep this line from Part 2: the screen stays out from under the status bar.
    5. Lines 16–19: four constraints tie textHello to the four edges of its parent. The editor draws them as springs.
  3. An empty screen.

    1. Click Design, two buttons to the right of Code.
    2. In Component Tree, click textHello.
    3. Press Delete. Keep the root, ConstraintLayout.

Done I see an empty screen: only ConstraintLayout in Component Tree.

Stuck? 3 symptoms · the file
  • Two screens side by side in the preview The second one is the blueprint. In the first menu of the preview’s toolbar, pick Design.
  • The preview is tiny, or cut off Click the bottom-right button of the preview: it zooms to fit.
  • The root, or its fitsSystemWindows line, is gone Paste this file over yours.

The files at the end of this step

res › layout › activity_main.xmlReplace the whole file
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

The four layouts

In Notes: the card

LinearLayout

One row or one column. layout_weight shares the free space.

In Notes: the list

FrameLayout

Layers, one over the other. A ScrollView is a FrameLayout that scrolls.

Older

RelativeLayout

Each view beside the parent or a sibling. ConstraintLayout replaced it.

In Notes: the screen

ConstraintLayout

Each edge tied to another edge, in a flat tree.

  • From Swing: BoxLayout ≈ LinearLayout · BorderLayout: no Android twin · SpringLayout ≈ ConstraintLayout · JLabel, JTextField, JButton ≈ TextView, EditText, Button · addActionListener ≈ setOnClickListener (Part 7).
A layout is a container (ViewGroup) that places the views inside it.

Step 2 of 6

Place the header and the logo

10 min

Goal Tie a band to the screen’s top, and a logo to the band.

  • Layout activity_main.xml · Design · Code
  1. The band: a View.

    1. Drag a View from PaletteWidgets onto the screen. It fills the whole screen.
    2. In Attributes, click the id field, type header, then press Enter.
    3. A Rename window opens: click Refactor.
    Rename A dialogFull size
    The Rename window: Rename ID Resource 'view' and its usages to: header, with Refactor, Preview and Cancel below.
    1. The new id: header.
    2. Refactor: renames the id everywhere it is used.
  2. Tie it to three edges, then size it.

    1. In Attributes, under Layout, find the Constraint Widget: a square with a + on each side.
    2. Click its + on top, then the one on the left, then the one on the right.
    3. A margin box appears beside each one. In each box, select the value with Ctrl+A, type 16, then press Enter.
    4. In layout_width, type 0dp, then press Enter: the band stretches between its constraints.
    5. In layout_height, type 168dp, then press Enter.
    Attributes › Layout Layout editor · centre
  3. The logo: an ImageView.

    1. Drag an ImageView from PaletteCommon to the screen’s top left corner.
    2. A Pick a Resource window opens: click ic_launcher_foreground, then OK.
  4. Type The band’s colour, in Code.

    1. Click Code, at the top right of the editor.
    2. Make header match the panel: type the line marked +.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="…@+id/imageLogo" android:layout_width="wrap_content36dp" android:layout_height="wrap_content36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />empty line
    </androidx.constraintlayout.widget.ConstraintLayout>
  5. Type The logo, in Code.

    1. Make imageLogo match the panel, mark by mark. A code line without a mark is already in your file.
    2. Your ImageView has tools:layout_editor_… lines? Your drop was not in the corner: delete them too.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="…@+id/imageLogo" android:layout_width="wrap_content36dp" android:layout_height="wrap_content36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />empty line
    </androidx.constraintlayout.widget.ConstraintLayout>

    @+id/header creates the id; @id/header points to it. dp: a size that looks the same on every screen.

Done In Design, I see an orange band, the robot at its top left.

Stuck? 4 symptoms · the file
  • The ImageView got tools:layout_editor_… lines Your drop was not in the corner. Delete those lines, then end the app:srcCompat line with />.
  • A value in Attributes went wrong Type it in Code instead: the file below shows each attribute of the band.
  • @id/header is red The band’s id is not exactly header. In the band’s <View, the id line reads android:id="@+id/header".
  • The XML turns red after you typed A view ends with no />, or with two: a deleted line took it, or you typed it twice. Keep one, at the end of the view’s last line, as in the file below.

The files at the end of this step

res › layout › activity_main.xmlReplace the whole file
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
<View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
</androidx.constraintlayout.widget.ConstraintLayout>

Step 3 of 6

Add the title and the card

12 min

Goal Add the title, then a white card that holds three views.

  • Layout activity_main.xml · Design · Code
  1. The title: a TextView.

    1. Click Design. Drag a TextView from PaletteCommon to just under the logo.
    2. In Attributes, type the id textAppTitle, then press Enter.
    3. Rename opens: click Refactor.
  2. The card: a vertical LinearLayout.

    1. Drag a LinearLayout (vertical) from PaletteLayouts to under the band. Two read LinearLa…: take the second, with the rows icon.
    2. In Attributes, type the id composer, then press Enter. No Rename this time: the view had no id.
  3. Three views in the card, one table row at a time.

    1. Drag the view from its Palette tab onto the row in Drop it onto, in Component Tree.
    2. Click what Then click names: the new row.
    3. In Attributes, type its id, press Enter, then click Refactor.
    The three views of the card, in order
    View (Palette tab) → idDrop it ontoThen click
    1Plain Text (Text) → editTitlethe composer rowcomposer’s ›, then the new row inside it
    2Multiline Text (Text) → editBodythe lower half of the editTitle rowthe new row, under editTitle
    3Button (Common) → buttonAddthe lower half of the editBody rowthe new row, under editBody
    Palette · Component Tree Layout editor · centre
  4. Type The title, in Code.

    1. Click Code. Make textAppTitle match the panel, mark by mark.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="TextViewNotes" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <LinearLayout android:id="@+id/composer" android:layout_width="…0dp" android:layout_height="…wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…"> android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Title" android:inputType="text" /> android:text="Name" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
    <Button android:id="@+id/buttonAdd" android:layout_width="match_parentwrap_content" android:layout_height="wrap_content" android:text="ButtonAdd" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    wrap_content: as big as the content. match_parent: as big as the parent. sp: a text size that also follows the phone’s font size.

  5. Type The card, in Code.

    1. Make composer match the panel, mark by mark.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="TextViewNotes" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <LinearLayout android:id="@+id/composer" android:layout_width="…0dp" android:layout_height="…wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…"> android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">Android Studio may write </LinearLayout> right after this >: delete it. The card closes after the button.
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Title" android:inputType="text" /> android:text="Name" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
    <Button android:id="@+id/buttonAdd" android:layout_width="match_parentwrap_content" android:layout_height="wrap_content" android:text="ButtonAdd" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
  6. Type The card’s three views.

    1. Make editTitle, editBody and buttonAdd match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="TextViewNotes" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <LinearLayout android:id="@+id/composer" android:layout_width="…0dp" android:layout_height="…wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…"> android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:hint="Title" android:inputType="text" /> android:text="Name" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
    <Button android:id="@+id/buttonAdd" android:layout_width="match_parentwrap_content" android:layout_height="wrap_content" android:text="ButtonAdd" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

Done In Design, I see the white card overlapping the band.

Stuck? 7 symptoms · the file
  • “Name” shows in the first field The line android:text="Name" is still there. Delete it, and end the line above it with />, as the panel shows.
  • The XML turns red after you typed A closing went with a deleted line, you typed it twice, or Android Studio added a </LinearLayout> after composer’s >. textAppTitle and each field end with one />; composer’s last attribute ends with > only.
  • The three views are not in the table’s order A drop onto the open composer row puts the view first. Click the view’s row, then drag it onto the lower half of the row it must follow.
  • No Rename window opens after an id The view had no id yet: the id is written at once. Go on.
  • A view is not where the page says in the Palette Click the magnifier at the top of the Palette and type its name. In Layouts, both LinearLayouts read LinearLa…: hover one to read its full name; the vertical one has the rows icon.
  • A field or the button sits outside the white card In Component Tree, it is beside composer, not inside it: click its row, then drag it onto the row the table names (column Drop it onto).
  • @id/imageLogo is red The logo’s id is not exactly imageLogo: its id line must read android:id="@+id/imageLogo".

The files at the end of this step

res › layout › activity_main.xmlReplace the whole file
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
<View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
<LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
<EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:inputType="text" />
<EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
<Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Step 4 of 6

Break a constraint

6 min

Goal Remove the card’s top constraint; see where the phone puts it.

  • Layout activity_main.xml · Split
  • Emulator

Predict first

Without its top constraint, where is the card on the phone?

See the answer

At the top: with no vertical constraint, the phone draws a view at the top of its parent (rule 1, under the result). The editor shows another place only if a drag left a tools: position, which the phone never sees.

  1. Type Delete the card’s top constraint.

    1. Click Split, at the top right of the editor.
    2. In composer, delete the struck part of the marked line. Keep its >: it closes the tag.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:inputType="text" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
  2. ▶ Run 'app'.

  3. Put it back.

    1. Click in the code, then press Ctrl+Z: the line comes back.
    2. ▶ again: the card is back under the band.
The phone after the break: the white card sits at the top of the screen and covers the band’s logo and title.

You should see After b, the card at the top, in the editor too (red in Component Tree). After c, the card under the band again.

Done I see the card jump, then come back.

What happened

It builds and runs: ▶ does not run lint, Android Studio’s code checker. Lint marks the card in red, with this message:

You should seeThis view is not constrained vertically: at runtime it will jump to the top unless you add a vertical constraint

Rule 1: the phone draws the card at the top. Ctrl+Z puts the line back.

  • Rule 1. Every view needs one horizontal and one vertical constraint, or the phone draws it at the top left.
  • Rule 2. 0dp = stretch between my constraints. For a direct child of a ConstraintLayout, never match_parent.
  • Rule 3. A margin acts only on a side that has a constraint.
The three rules of ConstraintLayout. The editor may show a view where a drag left it; the phone applies rule 1.
Stuck? 2 symptoms · the file
  • The XML turns red after the delete The > went with the line. Press Ctrl+Z, then select from app: to the last quote only, and delete.
  • Ctrl+Z does not bring the line back Paste this file over yours, then ▶.

The files at the end of this step

res › layout › activity_main.xmlReplace the whole file
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
<View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
<LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
<EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:inputType="text" />
<EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
<Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Step 5 of 6

Add the rest of the skeleton

5 min · B: 1 h

Goal Choose a way: A pastes the rest, B builds it by hand. Both give the same file.

  • Layout activity_main.xml · Design · Code
  • Emulator
A Paste the file 5 min · in class
  1. Paste Replace the whole file.

    1. Click Copy the file, at the top right of the panel below.
    2. In Code, click in the text, press Ctrl+A, then Ctrl+V.
    res › layout › activity_main.xmlReplace the whole file
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="YOUR NOTES" android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="Tap to open · hold to delete" android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    <ScrollView android:id="@+id/scrollNotes" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textListHint">
    <LinearLayout android:id="@+id/notesContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" /> </ScrollView>
    <TextView android:id="@+id/textEmpty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:gravity="center" android:text="No notes yet.\nWrite your first one above." android:textSize="16sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/scrollNotes" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    The new file gives each new view an id, and adds a LinearLayout without one. Your seven views keep their ids; buttonAdd now sits in that LinearLayout. Whole file shows the file, the new lines marked.

B Build it by hand about 1 h · optional: at home, or if you finish early

Start from your file after 3.4: 3.3’s. In doubt, first paste the file in 3.4’s Stuck?. Six parts, in order. Tick each part when it is done: when you come back, the first part not ticked is already open.

B1 The count beside the title 8 min
  1. A TextView under the title, in Component Tree.

    1. Click Design. Drag a TextView from PaletteCommon onto the lower half of the textAppTitle row in Component Tree: a line shows under it.
    2. Click the new row, just under textAppTitle.
    3. In Attributes, type the id textCount, press Enter, then click Refactor.
  2. Type The logo and the count, in Code.

    1. Click Code. Make imageLogo and textCount match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="TextView0" /> android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:inputType="text" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start|top" android:hint="Write something…" android:inputType="textMultiLine" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    Baseline: the 0 sits on the title’s line of text.

You should see In Design, a small white 0 right of Notes, on the same line.

Stuck? 2 symptoms
  • textCount is not just under textAppTitle in Component Tree Click its row, then drag it onto the lower half of the textAppTitle row. Delete any tools:layout_editor_… line it got.
  • The 0 is not right of Notes One of textCount’s two app:layout_constraint… lines is missing or misspelt: both name @id/textAppTitle.
B2 The fields and the error line 12 min
  1. A TextView under the second field.

    1. Click Design.
    2. In Component Tree, drag a TextView from PaletteCommon onto the lower half of the editBody row.
    3. Click the new row, just under editBody.
    4. In Attributes, type the id textError, press Enter, then click Refactor.
  2. Type The two fields, in Code.

    1. Click Code. Make editTitle and editBody match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="texttextCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="start|toptop" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLinetextMultiLine|textCapSentences" /> android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="match_parentwrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="TextViewGive your note a title first." /> android:textSize="14sp" android:visibility="gone" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    The |: AltGr+6 on an AZERTY keyboard.

  3. Type The error line.

    1. Make textError match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="texttextCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="start|toptop" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLinetextMultiLine|textCapSentences" /> android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="match_parentwrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="TextViewGive your note a title first." /> android:textSize="14sp" android:visibility="gone" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add" /> </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    gone: hidden, and it takes no room.

You should see In Design, the second field is three lines tall. textError is in Component Tree, not on the screen: it is gone.

Stuck? 2 symptoms
  • textError is not just under editBody In Component Tree, click its row, then drag it onto the lower half of the editBody row.
  • The XML turns red after you typed A closing went with an edit, or you typed it twice: each view’s last line ends with one />, as in the panels.
B3 The card’s last row 12 min
  1. A row under the error line. It needs no id.

    1. Click Design.
    2. In Component Tree, drag a LinearLayout (horizontal) from PaletteLayouts onto the lower half of the textError row. It is the first LinearLa….
  2. Two views in the row.

    1. Drag a TextView from PaletteCommon onto the new LinearLayout row.
    2. Click the › at the left of that row: it opens.
    3. Drag a Button from PaletteCommon onto the lower half of the new TextView row, under the new LinearLayout.
  3. Their ids.

    1. Click the new TextView row, under the new LinearLayout.
    2. In Attributes, type the id textCounter, press Enter, then click Refactor.
    3. Click the new Button row, under it.
    4. In Attributes, type the id buttonClear, press Enter, then click Refactor.
  4. Move Add into the row.

    1. In Component Tree, click the buttonAdd row.
    2. Drag it onto the lower half of the buttonClear row: it moves into the row, last.
    Component Tree Layout editor · centre
  5. Type The row, in Code.

    1. Click Code. Make the row and its three views match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parentwrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="wrap_content0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="TextView0 / 140" /> android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="ButtonClear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout>empty line </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

    style= takes no android:.

You should see In Design, one row at the card’s bottom: 0 / 140 at the left, then Clear and Add.

Stuck? 3 symptoms
  • The three views stand one under the other The row is a vertical LinearLayout: in its android:orientation line, change vertical to horizontal.
  • Add is not last in the row In Component Tree, click buttonAdd, then drag it onto the lower half of buttonClear’s row, not onto the LinearLayout row.
  • error: attribute android:style not found. In buttonClear, write style= without android:.
B4 The list’s title and hint 15 min
  1. Two TextViews under the card.

    1. Click Design. Drag a TextView from PaletteCommon to the empty screen under the card, at the left.
    2. In Attributes, type the id textListTitle, press Enter, then click Refactor.
    3. Drag another TextView to its right.
    4. In Attributes, type the id textListHint, press Enter, then click Refactor.
  2. Type The list’s title, in Code.

    1. Click Code. Make textListTitle match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="TextViewYOUR NOTES" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="wrap_content0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="TextViewTap to open · hold to delete" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    </androidx.constraintlayout.widget.ConstraintLayout>
  3. Type The hint.

    1. Make textListHint match the panel. No · key? Select it in the panel, then press Ctrl+C.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="TextViewYOUR NOTES" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="wrap_content0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="TextViewTap to open · hold to delete" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    0dp: the hint stretches to the right edge.

You should see In Design, YOUR NOTES in bold under the card, at the left; the hint on the same line, against the right edge.

Stuck? 2 symptoms
  • A TextView went into the white card In Component Tree it sits inside composer. Press Ctrl+Z, then drop it lower, on the empty screen.
  • @id/composer or @id/textListTitle is red An id is misspelt: the card’s is composer, the list title’s textListTitle.
B5 The list and its empty message 18 min
  1. The list: a ScrollView.

    1. Click Design.
    2. Drag a ScrollView from PaletteCommon to under YOUR NOTES.
    3. In Attributes, type the id scrollNotes, then press Enter. No Rename: it had no id.
    4. In Component Tree, click the › of the scrollNotes row, then the LinearLayout row inside it.
    5. In Attributes, type the id notesContainer, then press Enter.
  2. The empty message: a TextView.

    1. Drag a TextView from PaletteCommon onto the orange band, right of Notes. Over the card it would go inside it; over the list, nothing happens.
    2. In Attributes, type the id textEmpty, press Enter, then click Refactor.
    Palette · Layout editor Layout editor · centre
  3. Type The list, in Code.

    1. Click Code. Make scrollNotes and notesContainer match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="YOUR NOTES" android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="Tap to open · hold to delete" android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    <ScrollView android:id="@+id/scrollNotes" android:layout_width="…0dp" android:layout_height="…0dp" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…"> android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textListHint">
    <LinearLayout android:id="@+id/notesContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" /> </ScrollView>
    <TextView android:id="@+id/textEmpty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:gravity="center" android:text="TextViewNo notes yet.\nWrite your first one above." tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="16sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/scrollNotes" />
    </androidx.constraintlayout.widget.ConstraintLayout>
  4. Type The empty message.

    1. Make textEmpty match the panel.
    res › layout › activity_main.xmlEdit the marked lines
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="YOUR NOTES" android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="Tap to open · hold to delete" android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    <ScrollView android:id="@+id/scrollNotes" android:layout_width="…0dp" android:layout_height="…0dp" tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…"> android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textListHint">
    <LinearLayout android:id="@+id/notesContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" /> </ScrollView>
    <TextView android:id="@+id/textEmpty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:gravity="center" android:text="TextViewNo notes yet.\nWrite your first one above." tools:layout_editor_absoluteX="…" tools:layout_editor_absoluteY="…" /> android:textSize="16sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/scrollNotes" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    \n is a backslash (AltGr+8 on AZERTY) then n, not Enter.

You should see In Design, nothing new under YOUR NOTES: the list is empty, textEmpty is gone. Click scrollNotes in Component Tree: its frame reaches the bottom.

Stuck? 3 symptoms
  • The ScrollView holds no LinearLayout in Component Tree Drop a LinearLayout (vertical) onto scrollNotes there, then give it the id notesContainer.
  • textEmpty landed inside the card Press Ctrl+Z, then drop it on the orange band, right of Notes.
  • The XML turns red after you typed scrollNotes’s last line ends with > (its LinearLayout sits inside it); notesContainer and textEmpty end with />.
B6 Compare your file with the full file 3 min
  1. Compare, without pasting.

    1. Click Copy the file on the panel below. Its message says to paste: don’t, only compare.
    2. In Code, click once in the text, then right-click and choose Compare with Clipboard.
    res › layout › activity_main.xmlReplace the whole file
    <?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
    <View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
    <ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
    <TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
    <TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
    <LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
    <EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
    <EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
    <TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
    <TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
    <Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
    <Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
    <TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="YOUR NOTES" android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
    <TextView android:id="@+id/textListHint" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="Tap to open · hold to delete" android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
    <ScrollView android:id="@+id/scrollNotes" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textListHint">
    <LinearLayout android:id="@+id/notesContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" /> </ScrollView>
    <TextView android:id="@+id/textEmpty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:gravity="center" android:text="No notes yet.\nWrite your first one above." android:textSize="16sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/scrollNotes" />
    </androidx.constraintlayout.widget.ConstraintLayout>

You should see A tab Clipboard vs activity_main.xml opens: Contents are identical. Your file is the full file, line for line. Close that tab.

Stuck? 2 symptoms
  • The tab lists differences Fix each one in your file, or paste the full file over yours: Part 4 cites its line numbers.
  • Only the … or the · differs One was typed by hand: copy it from the full file’s panel.
  1. Then, way A or B: ▶ Run 'app'.

The skeleton on the phone: an orange band with the robot and “Notes 0”, a white card with Title, Write something…, 0 / 140, Clear and Add, then YOUR NOTES and its hint. No style yet.

Done I see the skeleton: band, card, YOUR NOTES.

Stuck? 4 symptoms · the file
  • The XML is red everywhere after the paste The old text is still there. Press Ctrl+A, then paste again.
  • Red and yellow marks on the fields, the buttons and the ScrollView Accessibility and text checks: real advice, not build errors. The app still runs.
  • Way B: a view landed in the wrong place in Component Tree Press Ctrl+Z, then drop it again as its part says.
  • Way B: lost, or the compare lists many differences Paste the full file (way A) over yours: the same views, and the line numbers Part 4 cites.

The file at the end of this step is way A’s panel: Copy the file.

Go deeper The new attributes, one line each 2 min
res › layout › activity_main.xmlRead only
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity">
<View android:id="@+id/header" android:layout_width="0dp" android:layout_height="168dp" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:background="#C2410C" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
<ImageView android:id="@+id/imageLogo" android:layout_width="36dp" android:layout_height="36dp" android:layout_marginStart="16dp" android:layout_marginTop="20dp" android:contentDescription="Notes logo" app:layout_constraintStart_toStartOf="@id/header" app:layout_constraintTop_toTopOf="@id/header" app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView android:id="@+id/textAppTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="Notes" android:textColor="#FFFFFF" android:textSize="30sp" app:layout_constraintStart_toStartOf="@id/imageLogo" app:layout_constraintTop_toBottomOf="@id/imageLogo" />
<TextView android:id="@+id/textCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="0" android:textColor="#FFFFFF" android:textSize="14sp" app:layout_constraintBaseline_toBaselineOf="@id/textAppTitle" app:layout_constraintStart_toEndOf="@id/textAppTitle" />
<LinearLayout android:id="@+id/composer" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="120dp" android:layout_marginEnd="32dp" android:background="#FFFFFF" android:orientation="vertical" android:padding="16dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/header">
<EditText android:id="@+id/editTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Title" android:importantForAutofill="no" android:inputType="textCapSentences" />
<EditText android:id="@+id/editBody" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="top" android:hint="Write something…" android:importantForAutofill="no" android:inputType="textMultiLine|textCapSentences" android:maxLength="140" android:minLines="3" />
<TextView android:id="@+id/textError" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="Give your note a title first." android:textSize="14sp" android:visibility="gone" />
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:gravity="center_vertical" android:orientation="horizontal">
<TextView android:id="@+id/textCounter" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="0 / 140" android:textSize="12sp" />
<Button android:id="@+id/buttonClear" style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Clear" />
<Button android:id="@+id/buttonAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="4dp" android:text="Add" /> </LinearLayout> </LinearLayout>
<TextView android:id="@+id/textListTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="32dp" android:layout_marginTop="24dp" android:text="YOUR NOTES" android:textSize="12sp" android:textStyle="bold" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/composer" />
<TextView android:id="@+id/textListHint" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="32dp" android:gravity="end" android:text="Tap to open · hold to delete" android:textSize="12sp" app:layout_constraintBaseline_toBaselineOf="@id/textListTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/textListTitle" />
<ScrollView android:id="@+id/scrollNotes" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textListHint">
<LinearLayout android:id="@+id/notesContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" /> </ScrollView>
<TextView android:id="@+id/textEmpty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:gravity="center" android:text="No notes yet.\nWrite your first one above." android:textSize="16sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/scrollNotes" />
</androidx.constraintlayout.widget.ConstraintLayout>
  1. Baseline: the count’s text sits on the same line as the title’s.
  2. hint: the grey text shown while the field is empty.
  3. importantForAutofill="no" turns autofill off here. Without it, lint warns Missing autofillHints attribute.
  4. inputType sets the keyboard’s mode. Here, several lines and a capital at each sentence.
  5. maxLength stops the field at 140 characters.
  6. visibility="gone" hides it, and it takes no room. Java shows it in Part 7.
  7. layout_weight="1" gives the counter the row’s free space; Clear and Add keep their size.
  8. style= takes no prefix: android:style does not exist.
  9. 0dp: the hint stretches from the label to the right edge. A long hint wraps in its own column.
  10. The list hangs from the hint’s bottom: a hint on two lines pushes it down.

Step 6 of 6

Preview other screen sizes

3 min

Goal Show the screen on a tablet, then on the phone, upright.

  • Layout activity_main.xml · Design
  1. A tablet.

    1. Above the preview, click the device menu: it shows the phone’s name, here Pixel.
    2. Choose Medium Tablet: the preview turns landscape.
    The preview’s device menu A menuFull size
    The device menu of the preview, open: Reference Devices with Medium Phone, Foldable, Medium Tablet and Desktop, then the Phones, Tablets and Desktop submenus.
    1. The device menu (here Pixel).
    2. Medium Tablet: 1280 × 800 dp.
  2. The phone, upright.

    1. Click the device menu again, then choose AVD: Pixel 7.
    2. The phone stays on its side: click the orientation menu, left of the device menu.
    3. Choose Portrait.
    The orientation menu A menuFull size
    The orientation menu of the preview, open: Portrait, Landscape ticked, UI Mode; below, the skeleton of Part 3 in landscape.
    1. The orientation menu.
    2. Portrait · Landscape.

Done I see the card stretch; nothing jumps.

Stuck? 2 symptoms
  • The phone preview stays on its side A tablet pick turned it to landscape. In the orientation menu, pick Portrait.
  • No AVD: Pixel 7 in the device menu It lists your virtual phones: create the Pixel 7 first (Part 0, step 0.2).

No file changes in this step.

Now you

Run it on a tablet

Run the app on Part 0’s Medium Tablet. Stop the phone first: ■ in Device Manager.

See the answer

In the device menu of the toolbar, pick the tablet, then ▶. The band and the card stretch; nothing jumps. Why stop the phone? Two emulators at once can freeze a laptop. No tablet yet? In Device Manager, add a Medium Tablet as in Part 0’s Now you: no download.

The skeleton at the Medium Tablet’s size, in landscape (simulated on the phone emulator, 2560 × 1600 pixels): the band and the card stretch across the screen.
The skeleton at the tablet’s size

If it doesn’t work

  • A view jumps to the top on the phone It misses a constraint. Give it one horizontal and one vertical (rule 1).
  • match_parent gives odd results For a direct child of the ConstraintLayout, use 0dp between two constraints (rule 2).
  • A view went wrong after many drags Right-click it, then Clear Constraints of Selection, and tie it again. Avoid Infer Constraints: it guesses for you.
  • error: attribute android:style not found. Write style= without android:.
  • An attribute you typed is underlined in red The drag had already written it. Keep one copy, with the panel’s value.
  • The XML turns red after you type A tag ends with one > (or />). Type new attributes before it, never after.

End of the part

Recap

The editor keeps a view where you drop it; the phone follows its constraints: one horizontal, one vertical per view.

  • drag views and give them ids;
  • tie a view to the parent or to another view; use 0dp;
  • explain why a view without constraints jumps; preview other sizes.
Your app at the end of Part 3: the skeleton of the notes screen, hard-coded colours and no style yet.
Your app now
← Lab 1, all parts