Open app/res/layout/activity_quiz.xml. If you see a graphical preview of the file, select the Text tab at the bottom to see the backing XML.
Currently, activity_quiz.xml defines the default activity layout. The defaults change frequently, but the XML will look something like Listing 1.1.
Listing 1.1 Default activity layout (activity_quiz.xml
)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_quiz" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" tools:context="com.bignerdranch.android.geoquiz.QuizActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!"/> </RelativeLayout>
The default activity layout defines two widgets: a RelativeLayout and a TextView.
Widgets are the building blocks you use to compose a UI. A widget can show text or graphics, interact with the user, or arrange other widgets on the screen. Buttons, text input controls, and checkboxes are all types of widgets.
The Android SDK includes many widgets that you can configure to get the appearance and behavior you want. Every widget is an instance of the View class or one of its subclasses (such as TextView or Button).
Figure 1.9 shows how the RelativeLayout and TextView defined in Listing 1.1 would appear on screen.
But these are not the widgets you are looking for. The interface for QuizActivity requires five widgets:
a vertical LinearLayout
a TextView
a horizontal LinearLayout
two Buttons
Figure 1.10 shows how these widgets compose QuizActivity’s interface.
Now you need to define these widgets in activity_quiz.xml.
In the project tool window, find the app/res/layout directory, reveal its contents, and open activity_quiz.xml. Make the changes shown in Listing 1.2. The XML that you need to delete is struck through, and the XML that you need to add is in bold font. This is the pattern we will use throughout this book.
Do not worry about understanding what you are typing; you will learn how it works next. However, do be careful. Layout XML is not validated, and typos will cause problems sooner or later.
You will see errors on the three lines that start with android:text
.
Ignore these errors for now; you will fix them soon.
Listing 1.2 Defining widgets in XML (activity_quiz.xml
)
<RelativeLayoutandroid:id="@+id/activity_quiz"xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.bignerdranch.android.geoquiz.QuizActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"/></RelativeLayout><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="24dp" android:text="@string/question_text" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/true_button" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/false_button" /> </LinearLayout> </LinearLayout>
Compare your XML with the UI shown in Figure 1.10. Every widget has a corresponding XML element, and the name of the element is the type of the widget.
Each element has a set of XML attributes. Each attribute is an instruction about how the widget should be configured.
To understand how the elements and attributes work, it helps to look at the layout from a hierarchical perspective.
Your widgets exist in a hierarchy of View objects called the view hierarchy. Figure 1.11 shows the view hierarchy that corresponds to the XML in Listing 1.2.
The root element of this layout’s view hierarchy is a LinearLayout. As the root element, the LinearLayout must specify the Android resource XML namespace at http://schemas.android.com/apk/res/android.
LinearLayout inherits from a subclass of View named ViewGroup. A ViewGroup is a widget that contains and arranges other widgets. You use a LinearLayout when you want widgets arranged in a single column or row. Other ViewGroup subclasses are FrameLayout, TableLayout, and RelativeLayout.
When a widget is contained by a ViewGroup, that widget is said to be a child of the ViewGroup. The root LinearLayout has two children: a TextView and another LinearLayout. The child LinearLayout has two Button children of its own.
Let’s go over some of the attributes that you have used to configure your widgets.
The android:layout_width
and android:layout_height
attributes
are required for almost every type of widget.
They are typically set to either match_parent or wrap_content:
match_parent |
|
wrap_content |
(You may see fill_parent in some places. This deprecated value is equivalent to match_parent.)
For the root LinearLayout, the value of both the height and width attributes is match_parent. The LinearLayout is the root element, but it still has a parent – the view that Android provides for your app’s view hierarchy to live in.
The other widgets in your layout have their widths and heights set to wrap_content
.
You can see in Figure 1.10 how this determines their sizes.
The TextView is slightly larger than the text it contains due to its android:padding="24dp"
attribute.
This attribute tells the widget to add the specified amount of space to its contents when determining its size.
You are using it to get a little breathing room between the question and the buttons.
(Wondering about the dp
units? These are density-independent pixels,
which you will learn about in Chapter 9.)
The android:orientation
attribute on the two LinearLayout widgets determines whether their children will appear vertically or horizontally.
The root LinearLayout is vertical; its child LinearLayout is horizontal.
The order in which children are defined determines the order in which they appear on screen. In a vertical LinearLayout, the first child defined will appear topmost. In a horizontal LinearLayout, the first child defined will be leftmost. (Unless the device is set to a language that runs right to left, such as Arabic or Hebrew. In that case, the first child will be rightmost.)
The TextView and Button widgets have android:text
attributes.
This attribute tells the widget what text to display.
Notice that the values of these attributes are not literal strings. They are references to string resources.
A string resource
is a string that lives in a separate XML file called a strings file.
You can give a widget a hardcoded string, like android:text="True"
, but it is usually not a good idea.
Placing strings into a separate file and then referencing them is better because it makes localization easy.
The string resources you are referencing in activity_quiz.xml do not exist yet. Let’s fix that.
Every project includes a default strings file named strings.xml.
Open res/values/strings.xml. The template has already added one string resource for you. Add the three new strings that your layout requires.
Listing 1.3 Adding string resources (strings.xml
)
<resources> <string name="app_name">GeoQuiz</string> <string name="question_text">Canberra is the capital of Australia.</string> <string name="true_button">True</string> <string name="false_button">False</string> </resources>
(Depending on your version of Android Studio, you may have additional strings. Do not delete them. Deleting them could cause cascading errors in other files.)
Now, whenever you refer to @string/false_button in any XML file in the GeoQuiz project, you will get the literal string “False” at runtime.
If you had errors in activity_quiz.xml about the missing string resources, they should now be gone. (If you still have errors, check both files for typos.)
Although the default strings file is named strings.xml, you can name a strings file anything you want.
You can also have multiple strings files in a project.
As long as the file is located in res/values/,
has a resources
root element, and contains child string
elements, your strings will be found and used.
Your layout is now complete, and you can preview the layout in the graphical layout tool (Figure 1.12). First, make sure that your files are error free. Then return to activity_quiz.xml and open the preview tool window (if it is not already open) using the tab to the right of the editor.