Create XML layouts for Android

1. Before you begin

What you'll learn

  • How to read and write XML layouts in Android
  • How to build the layout for a simple form to take in user text input and choices

What you'll build

  • The UI for a tip calculator Android app

What you need

2. Start the project

Check out the tip calculator on Google: https://www.google.com/search?q=tip+calculator

e2362ae2473981eb.png

In this pathway, you'll build a simple version of a tip calculator as an Android app.

Developers will often work in this way—getting a simple version of the app ready and partially functioning (even if it doesn't look very good), and then making it fully functional and visually polished later.

By the end of this codelab, your tip calculator app will look like this:

e53459106e39e86.png

You will be using these UI elements that are provided by Android:

  • EditText - for entering and editing text
  • TextView - to display text like the service question and tip amount
  • RadioButton - a selectable radio button for each tip option
  • RadioGroup - to group the radio button options
  • Switch - an on/off toggle for choosing whether to round up the tip or not

Create an Empty Activity project

3. Read and understand XML

You will be looking at, and editing the XML file that defines the UI layout for this app. XML stands for eXtensible Markup Language, which is a way of describing data using a text-based document. Because XML is extensible and very flexible, it's used for many different things, including defining the UI layout of Android apps. You may recall from earlier codelabs that other resources like strings for your app are also defined in an XML file called strings.xml.
The UI for an Android app is built as a containment hierarchy of components (widgets), and the on-screen layouts of those components. Note those layouts are UI components themselves.

You describe the view hierarchy of UI elements on the screen. For example, a ConstraintLayout (the parent) can contain ButtonsTextViewsImageViews, or other views (the children). Remember, ConstraintLayout is a subclass of ViewGroup. It allows you to position or size child views in a flexible manner.

129a72a2d272b921.png

Containment hierarchy of an Android app

ab49d373ed5bacce.png

Each UI element is represented by an XML element in the XML file. Each element starts and ends with a tag, and each tag starts with a < and ends with a >. Just as you can set attributes on UI elements using the Layout Editor (design), the XML elements can have attributes, too. Simplified, the XML for the UI elements above might be something like this:

<ConstraintLayout>
   
<TextView
       
text="Hello World!">
   
</TextView>
</ConstraintLayout>
9e3f433a224ba1f4.png
Let's look at a real example.
  1. Open activity_main.xml (res > layout > activity_main.xml)
  2. You might notice the app shows a TextView with "Hello World!" within a ConstraintLayout, as you have seen in previous projects created from this template.

520f45bcfc7d1cf7.png

  1. Find the options for CodeSplit, and Design views in the upper right of the Layout Editor.
  2. Select the Code view. ae13d413ae4da131.png

This is what the XML in activity_main.xml looks like:

<?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"
   
tools:context=".MainActivity">

   
<TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Hello World!"
       
app:layout_constraintBottom_toBottomOf="parent"
       
app:layout_constraintLeft_toLeftOf="parent"
       
app:layout_constraintRight_toRightOf="parent"
       
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

There's a lot more going on than in the simplified example, but Android Studio does some things to help make the XML more readable, just as it does with your Kotlin code.

  1. Notice the indentation. Android Studio does this automatically to show you the hierarchy of elements. The TextView is indented because it is contained in the ConstraintLayout. The ConstraintLayout is the parent, and the TextView is the child. The attributes for each element are indented to show that they're part of that element.
  2. Notice the color coding—some things are in blue, some in green, and so on. Similar parts of the file are drawn in the same color to help you match them up. In particular, notice that Android Studio draws the start and end of tags of elements in the same color. (Note: the colors used in the codelab may not match what you see in Android Studio.)

XML tags, elements and attributes

Here's a simplified version of the TextView element so you can look at some of the important parts:

<TextView
   
android:text="Hello World!"
/>
The line with <TextView is the start of the tag, and the line with /> is the end of the tag. The line with android:text="Hello World!" is an attribute of the tag. It represents text that will be displayed by the TextView. These 3 lines are a commonly used shorthand called an empty-element tag. It would mean the same thing if you wrote it with a separate start-tag and end-tag, like this:
<TextView
   
android:text="Hello World!"
></TextView>
It's also common with an empty-element tag to write it on as few lines as possible and combine the end of the tag with the line before it. So you might see an empty-element tag on two lines (or even one line if it had no attributes):
<!-- with attributes, two lines -->
<TextView
   
android:text="Hello World!" />
The ConstraintLayout element is written with separate start and end tags, because it needs to be able to hold other elements inside it. Here's a simplified version of the ConstraintLayout element with the TextView element inside it:
<androidx.constraintlayout.widget.ConstraintLayout>
   
<TextView
       
android:text="Hello World!" />
</androidx.constraintlayout.widget.ConstraintLayout>
If you wanted to add another View as a child of the ConstraintLayout, like a Button below the TextView, it would go after the end of the TextView tag /> and before the end tag of the ConstraintLayout, like this:
<androidx.constraintlayout.widget.ConstraintLayout>
   
<TextView
       
android:text="Hello World!" />
   
<Button
       
android:text="Calculate" />
</androidx.constraintlayout.widget.ConstraintLayout>

More about XML for layouts

  1. Look at the tag for the ConstraintLayout, and notice that it says androidx.constraintlayout.widget.ConstraintLayout instead of just ConstraintLayout like the TextView. This is because ConstraintLayout is part of Android Jetpack, which contains libraries of code which offers additional functionality on top of the core Android platform. Jetpack has useful functionality you can take advantage of to make building apps easier. You'll recognize this UI component is part of Jetpack because it starts with "androidx".
  2. You may have noticed the lines that begin with xmlns:, followed by androidapp, and tools.
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"

The xmlns stands for XML namespace, and each line defines a schema, or vocabulary for attributes related to those words. The android: namespace, for example, marks attributes that are defined by the Android system. All of the attributes in the layout XML begins with one of those namespaces.

  1. Whitespace between XML elements doesn't change the meaning to a computer, but it can help make the XML easier for people to read.

Android Studio will automatically add some whitespace and indenting for readability. You'll learn later how to have Android Studio make sure your XML follows coding style conventions.

  1. You can add comments to XML, just like you would with Kotlin code. Start <!-- and end with -->.
<!-- this is a comment in XML -->

<!-- this is a
multi-line
Comment.
And another
Multi-line comment -->
  1. Note the first line of the file:
<?xml version="1.0" encoding="utf-8"?>

This indicates that the file is an XML file, but not every XML file includes this.

4. Build the layout in XML

5. Add tip options

Next you'll add radio buttons for the different tip options the user can choose from.

There should be three options:

  • Amazing (20%)
  • Good (18%)
  • Okay (15%)

If you're not sure how to do this, you can do a Google search. This is a great tool that developers use when they're stuck.

  1. Do a Google search for radio button android. The top result is a guide from the Android developers site on how to use radio buttons—perfect!

f5f1c6778ae7a5d.png

  1. Skim through the Radio Buttons guide.

Reading the description, you can confirm that you can use a RadioButton UI element in your layout for each radio button you need. Furthermore, you also need to group the radio buttons within a RadioGroup because only one option can be selected at a time.

There is some XML that looks like it would fit your needs. Read through it and see how RadioGroup is the parent view and the RadioButtons are child views within it.

  1. Go back to your layout in Android Studio to add the RadioGroup and RadioButton to your app.
  2. After the TextView element, but still within the ConstraintLayout, start typing out <RadioGroup. Android Studio will provide helpful suggestions to help you complete your XML. d87151d9eddf3428.png
  3. Set the layout_width and layout_height of the RadioGroup to wrap_content.
  4. Add a resource ID set to @+id/tip_options.
  5. Close the start tag with >.
  6. Android Studio adds </RadioGroup>. Like the ConstraintLayout, the RadioGroup element will have other elements inside it, so you might want to move it to its own line. 4401c4781d8e6cf9.gif
  7. Constrain the RadioGroup below the service question (vertically) and to the start of the parent (horizontally).
  8. Set the android:orientation attribute to vertical. If you wanted the RadioButtons in a row, you would set the orientation to horizontal.

The XML for the RadioGroup should look like this:

<RadioGroup
   
android:id="@+id/tip_options"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
android:orientation="vertical"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintTop_toBottomOf="@id/service_question">

</RadioGroup>

Add RadioButtons

  1. After the last attribute of the RadioGroup, but before the </RadioGroup> end tag, add a RadioButton.
<RadioGroup
   
android:id="@+id/tip_options"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
android:orientation="vertical"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintTop_toBottomOf="@id/service_question">

   
<!-- add RadioButtons here -->

</RadioGroup>
  1. Set the layout_width and layout_height to wrap_content.
  2. Assign a resource ID of @+id/option_twenty_percent to the RadioButton.
  3. Set the text to Amazing (20%).
  4. Close the tag with />.
<RadioGroup
   
android:id="@+id/tip_options"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
app:layout_constraintTop_toBottomOf="@id/service_question"
   
app:layout_constraintStart_toStartOf="parent"
   
android:orientation="vertical">

   
<RadioButton
       
android:id="@+id/option_twenty_percent"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Amazing (20%)" />

</RadioGroup>

6624b7a3b092cc63.png

Now that you've added one RadioButton, can you modify the XML to add 2 more radio buttons for the Good (18%) and Okay (15%) options?

This is what the XML for the RadioGroup and RadioButtons looks like:

<RadioGroup
   
android:id="@+id/tip_options"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
app:layout_constraintTop_toBottomOf="@id/service_question"
   
app:layout_constraintStart_toStartOf="parent"
   
android:orientation="vertical">

   
<RadioButton
       
android:id="@+id/option_twenty_percent"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Amazing (20%)" />

   
<RadioButton
       
android:id="@+id/option_eighteen_percent"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="Good (18%)" />

   
<RadioButton
       
android:id="@+id/option_fifteen_percent"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="OK (15%)" />

</RadioGroup>

fa6105c317459f54.png

Add a default selection

Currently, none of the tip options are selected. It would be nice to select one of the radio button options by default.

There's an attribute on the RadioGroup where you can specify which button should be checked initially. It's called checkedButton, and you set it to the resource ID of the radio button you want selected

  1. On the RadioGroup, set the android:checkedButton attribute to @id/option_twenty_percent.
<RadioGroup
   android:id="@+id/tip_options"
   android:checkedButton="@id/option_twenty_percent"
   ...

Notice in the Design Editor that the layout has updated. The 20% tip option is selected by default—cool! Now it's starting to look like a tip calculator!

91bfc37972c3416f.png

Here is what the XML looks like so far:

<?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"
   
tools:context=".MainActivity">

   
<EditText
       
android:id="@+id/cost_of_service"
       
android:hint="Cost of Service"
       
android:layout_height="wrap_content"
       
android:layout_width="160dp"
       
app:layout_constraintStart_toStartOf="parent"
       
app:layout_constraintTop_toTopOf="parent"
       
android:inputType="numberDecimal"/>

   
<TextView
       
android:id="@+id/service_question"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="How was the service?"
       
app:layout_constraintTop_toBottomOf="@id/cost_of_service"
       
app:layout_constraintStart_toStartOf="parent" />

   
<RadioGroup
       
android:id="@+id/tip_options"
       
android:checkedButton="@id/option_twenty_percent"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
app:layout_constraintTop_toBottomOf="@id/service_question"
       
app:layout_constraintStart_toStartOf="parent"
       
android:orientation="vertical">

       
<RadioButton
           
android:id="@+id/option_twenty_percent"
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="Amazing (20%)" />

       
<RadioButton
           
android:id="@+id/option_eighteen_percent"
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="Good (18%)" />

       
<RadioButton
           
android:id="@+id/option_fifteen_percent"
           
android:layout_width="wrap_content"
           
android:layout_height="wrap_content"
           
android:text="OK (15%)" />
   
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>

6. Complete the rest of the layout

You're on the last part of the layout now. You'll add a SwitchButton, and a TextView to display the tip amount.

Add a Switch for rounding up the tip

Next, you'll use a Switch widget to allow the user to select yes or no for rounding up the tip.

You want the Switch to be as wide as the parent, so you might think the width should be set to match_parent. As noted earlier, you can't set match_parent on UI elements in a ConstraintLayout. Instead, you need to constrain the start and end edges of the view, and set the width to 0dp. Setting the width to 0dp tells the system not to calculate the width, just try to match the constraints that are on the view.

  1. Add a Switch element after the XML for the RadioGroup.
  2. As noted above, set the layout_width to 0dp.
  3. Set the layout_height to wrap_content. This will make the Switch view as tall as the content inside.
  4. Set the id attribute to @+id/round_up_switch.
  5. Set the text attribute to Round up tip?. This will be used as a label for the Switch.
  6. Constrain the start edge of the Switch to the start edge of the parent, and the end to the end of the parent.
  7. Constrain the top of the Switch to the bottom of the tip_options.
  8. Close the tag with />.

It would be nice if the switch was turned on by default, and there's an attribute for that, android:checked, where the possible values are true (on) or false (off).

  1. Set the android:checked attribute to true.

Putting that all together, the XML for the Switch element looks like this:

<Switch
   
android:id="@+id/round_up_switch"
   
android:layout_width="0dp"
   
android:layout_height="wrap_content"
   
android:checked="true"
   
android:text="Round up tip?"
   
app:layout_constraintEnd_toEndOf="parent"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintTop_toBottomOf="@id/tip_options" />

22a721c15c365e51.png

Add the Calculate button

Next you'll add a Button so the user can request that the tip be calculated. You want the button to be as wide as the parent, so the horizontal constraints and width are the same as they were for the Switch.

  1. Add a Button after the Switch.
  2. Set the width to 0dp, as you did for the Switch.
  3. Set the height to wrap_content.
  4. Give it a resource ID of @+id/calculate_button, with the text "Calculate".
  5. Constrain the top edge of Button to the bottom edge of the Round up tip? Switch.
  6. Constrain the start edge to the start edge of the parent and the end edge to the end edge of the parent.
  7. Close the tag with />.

Here's what the XML for the Calculate Button looks like.

<Button
   
android:id="@+id/calculate_button"
   
android:layout_width="0dp"
   
android:layout_height="wrap_content"
   
android:text="Calculate"
   
app:layout_constraintTop_toBottomOf="@id/round_up_switch"
   
app:layout_constraintStart_toStartOf="parent"
   
app:layout_constraintEnd_toEndOf="parent" />

ccabc4f3a8960029.png

Add tip result

You're almost done with the layout! In this step you'll add a TextView for the tip result, putting it below the Calculate button, and aligned with the end instead of the start like the other UI elements.

  1. Add a TextView with a resource ID named tip_result and the text Tip Amount.
  2. Constrain the ending edge of the TextView to the ending edge of the parent.
  3. Constrain the top edge to the bottom edge of the Calculate button.
<TextView
   
android:id="@+id/tip_result"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
app:layout_constraintEnd_toEndOf="parent"
   
app:layout_constraintTop_toBottomOf="@id/calculate_button"
   
android:text="Tip Amount" />

a2b20f3286d4f8b6.png

Run the app

b272e8343c3b8c16.png

Great job, especially if this is your first time working with XML!

7. Adopt good coding practices

Extract the strings

You may have noticed the warnings about hard-coded strings. Recall from the earlier codelabs that extracting strings to a resource file makes it easier to translate your app to other languages and to reuse strings. Go through activity_main.xml and extract all the string resources.

  1. Click on a string; hover over on the yellow light bulb icon that appears, then click on the triangle next to it; choose Extract String Resource. The default names for the string resources are fine. If you want, for the tip options you can use amazing_servicegood_service, and okay_service to make the names more descriptive.

Now verify the string resources you just added.

  1. If the Project window isn't showing, click the Project tab on the left side of the window.
  2. Open app > res > values > strings.xml to see all the UI string resources.
<resources>
   
<string name="app_name">Tip Time</string>
   
<string name="cost_of_service">Cost of Service</string>
   
<string name="how_was_the_service">How was the service?</string>
   
<string name="amazing_service">Amazing (20%)</string>
   
<string name="good_service">Good (18%)</string>
   
<string name="ok_service">Okay (15%)</string>
   
<string name="round_up_tip">Round up tip?</string>
   
<string name="calculate">Calculate</string>
   
<string name="tip_amount">Tip Amount</string>
</resources>

Reformat the XML

Android Studio provides various tools to tidy up your code and make sure it follows recommended coding conventions.

  1. In activity_main.xml, choose Edit > Select All.
  2. Choose Code > Reformat Code.

This will make sure the indenting is consistent, and it may reorder some of the XML of UI elements to group things, for example, putting all the android: attributes of one element together.

8. Summary

  • XML (Extensible Markup Language) is a way of organizing text, made of tags, elements, and attributes.
  • Use XML to define the layout of an Android app.
  • Use EditText to let the user input or edit text.
  • An EditText can have a hint to tell the user what is expected in that field.
  • Specify the android:inputType attribute to limit what type of text the user can input into an EditText field.
  • Make a list of exclusive options with RadioButtons, grouped with a RadioGroup.
  • RadioGroup can be vertical or horizontal, and you can specify which RadioButton should be selected initially.
  • Use a Switch to let the user toggle between two options.
  • You can add a label to a Switch without using a separate TextView.
  • Each child of a ConstraintLayout needs to have vertical and horizontal constraints.
  • Use "start" and "end" constraints to handle both Left to Right (LTR) and Right to Left (RTL) languages.
  • Names of the constraint attributes follow the form layout_constraint<Source>_to<Target>Of.
  • To make a View as wide as the ConstraintLayout it's in, constrain the start and end to the start and end of the parent, and set the width to 0dp.

9 Learn more

Below are links to more documentation on the topics covered. You can find all of the documentation for Android Development on developer.android.com. And don't forget you can do a Google search if you get stuck on something.

10. Practice on your own

Do the following:

  • Create a different calculator app, like a unit converter for cooking, to convert milliliters to or from fluid ounces, grams to or from cups, and so on. What fields do you need?


0 Comments

Brand creation, trend analysis & style consulting

Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since.