Android Programming with Kotlin for Beginners
上QQ阅读APP看书,第一时间看更新

Building a menu with LinearLayout

LinearLayout is probably the simplest layout that Android offers. As the name suggests, all the UI items within it are laid out linearly. You have just two choices – vertical and horizontal. By adding the following line of code (or editing via the Attribute window), you can configure a LinearLayout to lay things out vertically:

android:orientation="vertical"

You can then (as you could probably have guessed) change "vertical" to "horizontal" to lay things out horizontally.

Before we can do anything with LinearLayout, we need to add one to a layout file. And, as we are building three layouts in this project, we also need a new layout file.

Adding a LinearLayout to the project

In the project window, expand the res folder. Now right-click the layout folder and select New. Notice that there is an option for Layout resource file, as shown in the following screenshot:

Select Layout resource file and you will see the New Resource File dialog window:

In the File name field, enter main_menu. The name is arbitrary, but this layout is going to be our "main" menu that is used to select the other layouts, so the name seems appropriate.

Notice that it has already selected LinearLayout as the Root element option.

Click the OK button, and Android Studio will generate a new LinearLayout in an XML file called main_menu and place it in the layout folder ready for us to build our new main menu UI. Android Studio will also open the UI designer with the palette on the left and the attributes window on the right.

Preparing your workspace

Adjust the windows by dragging and resizing their borders (as you can in most windowed apps) to make the palette, design, and attributes as clear as possible, but no bigger than necessary. This small screenshot shows the approximate window proportions I chose to make designing our UI and exploring the XML as clear as possible. The detail in the screenshot is not important:

Observe that I have made the project, palette, and attribute windows as narrow as possible, yet without obscuring any content. I have also closed the build/logcat window at the bottom of the screen, the result being that I have a nice clear canvas on which to build the UI.

Examining the generated XML

Click on the Text tab and we will have a look at the current state of the XML code that forms our design at this stage. Here is the code so that we can discuss this further:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"

 android:orientation="vertical" 
 android:layout_width="match_parent"
 android:layout_height="match_parent">

</LinearLayout>

We have the usual starting and closing tags and, as we could have predicted, they are <LinearLayout and </LinearLayout>. There is no child element yet, but there are three attributes. We know they are attributes, and not children, of the LinearLayout, because they appear before the first closing >. The three attributes that define this LinearLayout have been highlighted in the previous code for clarity.

The first attribute is android:orientation, or, more succinctly, we will just refer to the attributes without the android: part. The orientation attribute has a value of vertical. This means that, when we start to add items to this layout, it will arrange them vertically from top to bottom. We could change the value from vertical to horizontal and it would lay things out from left to right.

The next two attributes are layout_width and layout_height. These determine the size of the LinearLayout. The value given to both attributes is match_parent. The parent of a layout is the entire available space. By matching the parent horizontally and vertically, therefore, the layout will fill the entire space available.

Adding a TextView to the UI

Switch back to the Design tab and we will add some elements to the UI.

First, find the TextView in the palette. This can be found in both the Common and Text categories. Left-click and drag the TextView onto the UI, and notice that it sits neatly at the top of the LinearLayout.

Look at the XML on the Text tab and confirm that it is a child of the LinearLayout and that it is indented by one tab to make this clear. Here is the code for the TextView without the surrounding code for the LinearLayout:

<TextView
   android:id="@+id/textView"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:text="TextView" />

Notice that it has four attributes: id, in case we need to refer to it from another UI element or from our Kotlin code; layout_width is set to match_parent, which means the that TextView stretches across the whole width of the LinearLayout; a layout_height attribute is set to wrap_content, which means the that TextView is precisely tall enough to contain the text within it; and finally, for now, it has a text element that determines the actual text it will display, and this is currently just set to TextView.

Switch back to the design tab and we will make some changes.

We want this text to be the heading text of this screen, which is the main menu screen. In the attributes window, click the search icon, type text into the search box, and change the text attribute to Menu, as shown in the following screenshot:

Tip

You can find any attribute by searching or just by scrolling through the options. When you have found the attribute you want to edit, left-click it to select it and then press the Enter key on the keyboard to make it editable.

Next, find the textSize attribute using your preferred search technique and set textSize to 50sp. When you have entered this new value, the text size will increase.

The sp stands for scalable pixels. This means that when the user changes the font size settings on their Android device, the font will dynamically rescale itself.

Now, search for the gravity attribute and expand the options by clicking the little arrow indicated in the following screenshot:

Set gravity to center_horizontal, as shown in the following screenshot:

The gravity attribute refers to the gravity within the TextView itself, and our change has the effect of moving the actual text inside the TextView to the center.

Tip

Note that gravity is different to layout_gravity. The layout_gravity property sets the gravity within the layout: in this case, the parent LinearLayout. We will use layout_gravity later in this project.

At this point, we have changed the text of the TextView, increased its size, and centered it horizontally. The UI designer should now look like the following diagram:

A quick glance at the Text tab to see the XML would reveal the following code:

<TextView
   android:id="@+id/textView"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:gravity="center_horizontal"
   android:text="Menu"
   android:textSize="50sp" />

You can see the new attributes as follows: gravity, which is set to center_horizontal; text, which has changed to Menu; and textSize, which is set to 50sp.

If you run the app, you might not see what you expected. This is because we haven't called setContentView in our Kotlin code to load the UI. You will still see the blank UI. We will fix this once we have made a bit more progress with the UI.

Adding a multi-line TextView to the UI

Switch back to Design tab, find the Multiline Text in the Text category of the palette, and drag it onto the design just below the TextView we added a moment ago.

Using your preferred search technique, set text to Select a layout type to view an example. The onClick attribute of each button will call a function which executes setContentView to load the new layout.

Your layout will now look like the following screenshot:

Your XML will be updated with another child in the LinearLayout, after the TextView, that looks like the following code:

<EditText
   android:id="@+id/editText"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:ems="10"
   android:inputType="textMultiLine"
   android:text="Select a layout type to view an example. 
         The onClick attribute of each button will call a function 
         which executes setContentView to load the new layout" />

You can see the details of the UI item and it turns out that the description on the palette of Multiline Text was not entirely obvious as to exactly what this would be. A look at the XML reveals that we have an inputType attribute, indicating that this text is editable by the user. There is also another attribute that we haven't seen before, and that is ems. The ems attribute controls how many characters can be entered per line, and the value of 10 was chosen automatically by Android Studio. However, another attribute, layout_width="match_parent", overrides this value because it causes the element to expand to fit its parent; in other words, to cover the whole width of the screen.

When you run the app (in the next section), you will see that the text is, indeed, editable – although, for the purposes of this demo app, it serves no practical purpose.