Open the Layout Editor

In the Project window, double-click activity_main.xml (app > res > layout > activity_main.xml) to open it. You should see the Layout Editor, with only the "Hello World" TextView in the center of the app.

Next you will add a Button to your app. A Button is a user interface (UI) element in Android that the user can tap to perform an action.

In this task, you add a Button below the "Hello World" TextView. The TextView and the Button will be located within a ConstraintLayout, which is a type of ViewGroup.

When there are Views within a ViewGroup, the Views are considered children of the parent ViewGroup. In the case of your app, the TextView and Button would be considered children of the parent ConstraintLayout.

Go ahead with adding a Button as a child of the existing ConstraintLayout in your app.

Note: Like in a family tree, in a view hierarchy, parent views can themselves be child views, and child views can be parents to other children.

Add a Button to the layout

Drag a Button from the Palette onto the Design view, positioning it below the "Hello World" TextView.

Below the Palette in the Component Tree, verify that the Button and TextView are listed under the ConstraintLayout (as children of the ConstraintLayout).

Notice an error that the Button is not constrained. Since the Button is sitting within a ConstraintLayout, you must set vertical and horizontal constraints to position it.

Position the Button

In this step you'll add a vertical constraint from the top of the Button to the bottom of the TextView. This will position the Button below the TextView.

In the Design view, at the top edge of the Button, press and hold the white circle with a blue border. Drag the pointer, and an arrow will follow the pointer. Release when you reach the bottom edge of the "Hello World" TextView. This establishes a layout constraint, and the Button slides up to just beneath the TextView.

Look at the Attributes on the right hand side of the Layout Editor.

In the Constraint Widget, notice a new layout constraint that is set to the bottom of the TextView, Top → BottomOf textView (0dp). (0dp) means there is a margin of 0. You also have an error for missing horizontal constraints.

Add a horizontal constraint from the left side of the Button to the left side of the parent ConstraintLayout.

Repeat on the right side, connecting the right edge of the Button to the right edge of the ConstraintLayout. The result should look like this:

With the Button still selected, the Constraint Widget should look like this. Notice two additional constraints that have been added: Start → StartOf parent (0dp) and End → EndOf parent (0dp). This means the Button is horizontally centered in its parent, the ConstraintLayout.

Run the app. It should look like the screenshot below. You can click on the Button, but it doesn't do anything yet. Let's keep going!

Change the Button text

You're going to make a couple more UI changes in the Layout Editor.

Instead of having the Button label show "Button", change it to something that indicates what the button is going to do: "Roll".

In the Layout Editor, with the Button selected, go to Attributes, change the text to Roll, and press the Enter (Return on the Mac) key.

In the Component Tree, an orange warning triangle appears next to the Button. If you hover the pointer over the triangle, a message appears. Android Studio has detected a hardcoded string ("Roll") in your app code and suggests using a string resource instead.

Having a hardcoded string means the app will be harder to translate into other languages and it is harder to reuse strings in different parts of your app. Fortunately, Android Studio has an automatic fix for you.

In the Component Tree, click on the orange triangle.

The full warning message opens.

At the bottom of the message, under Suggested Fix, click the Fix button. (You may need to scroll down.)

The Extract Resource dialog opens. To extract a string means to take the "Roll" text and create a string resource called roll in strings.xml (app > res > values > strings.xml). The default values are correct, so click OK.

Notice that in Attributes, the text attribute for the Button now says @string/roll, referring to the resource you just created.

In the Design view, the Button should still say Roll on it.

Style the TextView

The "Hello World!" text is quite small, and the message isn't relevant for your app. In this step you'll replace the small "Hello, World!" message with a number to show the rolled value, and make the font bigger, so it is easier to see.

In the Design Editor, select the TextView so that its attributes appear in the Attributes window.

Change the textSize of the TextView to 36sp, so that it's large and easy to read. You may need to scroll to find textSize.

Clear the text attribute of the TextView. You don't need to display anything in the TextView until the user rolls the dice.

However, it's very helpful to see some text in the TextView when you're editing the layout and code for your app. For this purpose, you can add text to the TextView that is only visible for the layout preview, but not when the app is running

.

Select the TextView in the Component Tree.

Under Common Attributes, find the text attribute, and below it, another text attribute with a tool icon. The text attribute is what will be displayed to the user when the app is running. The text attribute with a tool icon is the "tools text" attribute that is just for you as a developer.

Set the tools text to be "1" in the TextView (to pretend you have a dice roll of 1). The "1" will only appear in the Design Editor within Android Studio, but it will not appear when you run the app on an actual device or emulator.

Note that because this text is only viewed by app developers, you don't need to make a string resource for it.

Look at your app in the preview. The "1" is showing.

Run your app. This is what the app looks like when it's run on an emulator. The "1" is not showing. This is the correct behavior.

Great, you're done with the layout changes!

You have an app with a button, but if you tap the button, nothing happens. To change this, you'll need to write some Kotlin code that rolls the dice and updates the screen when the button is tapped.

In order to make this change, you need to understand a little bit more of how an Android app is structured.

An Activity provides the window in which your app draws its UI. Typically, an Activity takes up the whole screen of your running app. Every app has one or more activities. The top-level or first activity is often called the MainActivity and is provided by the project template. For example, when the user scrolls through the list of apps on their device and taps on the "Dice Roller" app icon, the Android System will start up the MainActivity of the app.

In your MainActivity code, you need to provide details on the Activity's layout and how the user should interact with it.

In the Birthday Card app, there is one Activity that displays the birthday message and image.

In the Dice Roller app, there is one Activity that displays the TextView and Button layout you just built.

For more complicated apps, there may be multiple screens and more than one Activity. Each Activity has a specific purpose.

For example, in a photo gallery app, you could have an Activity for displaying a grid of photos, a second Activity for viewing an individual photo, and a third Activity for editing an individual photo.

Open the MainActivity.kt file

You will add code to respond to a button tap in the MainActivity. In order to do this correctly, you need to understand more about the MainActivity code that's already in your app.

Navigate to and open the MainActivity.kt file (app > java > com.example.diceroller > MainActivity.kt). Below is what you should see. If you see import..., click on the ... to expand the imports.

You don't need to understand every single word of the above code, but you do need to have a general idea of what it does. The more you work with Android code, the more familiar it'll become, and the more you'll understand it.

Look at the Kotlin code for the MainActivity class, identified by the keyword class and then the name.

class MainActivity : AppCompatActivity() {
...
}

Notice that there is no main() function in your MainActivity.

Earlier, you learned that every Kotlin program must have a main() function. Android apps operate differently. Instead of calling a main() function, the Android system calls the onCreate() method of your MainActivity when your app is opened for the first time.

You'll learn about override in a later codelab (so don't worry about it for now). The rest of the onCreate() method sets up the MainActivity by using code from the imports and by setting the starting layout with setContentView().

Notice the lines beginning with import.

Android provides a framework of numerous classes to make writing Android apps easier, but it needs to know exactly which class you mean. You can specify which class in the framework to use in your code by using an import statement. For example, the Button class is defined in android.widget.Button.

Enable auto imports

It can become a lot of work to remember to add import statements when you use more classes. Fortunately, Android Studio helps you choose the correct imports when you are using classes provided by others. In this step you'll configure Android Studio to automatically add imports when it can, and automatically remove unused imports from your code.

In Android Studio, open the settings by going to File > Other Settings > Preferences for New Projects.

Expand Other Settings > Auto Import. In the Java and Kotlin sections, make sure Add unambiguous imports on the fly and Optimize imports on the fly (for current project) are checked. Note that there are two checkboxes in each section.The unambiguous imports settings tell Android Studio to automatically add an import statement, as long as it can determine which one to use. The optimize imports settings tell Android Studio to remove any imports that aren't being used by your code.

Save the changes and close settings by pressing OK.

Now that you know a little more about the MainActivity, you'll modify the app so that clicking the Button does something on the screen.

Display a message when the Button is clicked

In this step, you will specify that when the button is clicked, a brief message shows at the bottom of the screen.

Add the following code to the onCreate() method after the setContentView() call. The findViewById() method finds the Button in the layout. R.id.button is the resource ID for the Button, which is a unique identifier for it. The code saves a reference to the Button object in a variable called rollButton, not the Button object itself.

val rollButton: Button = findViewById(R.id.button)

Note: Android automatically assigns ID numbers to the resources in your app. For example, the Roll button has a resource ID, and the string for the button text also has a resource ID. Resource IDs are of the form R.<type>.<name>; for example, R.string.roll. For View IDs, the <type> is id, for example, R.id.button.

The code saves the reference to the Button object in a variable called rollButton, not the Button object itself.

Important: When it assigns an object to a variable, Kotlin doesn't copy the entire object each time, it saves a reference to the object. You can think of a reference as being like a Social Security number or other national ID number: the number refers to a person, but it isn't the person itself. When you copy the number, you don't copy the person.

Note: If enabling auto imports didn't work, Button will be highlighted in red. You can manually add the correct import by putting the text cursor within the word Button, then pressing Alt+Enter (Option+Enter on a Mac).

Next you need to associate code with the Button, so that the code can be executed when the Button is tapped. A click listener is some code for what to do when a tap or click happens. You can think of it as code that is just sitting, "listening" for the user to click, in this case, on the Button.

Use the rollButton object and set a click listener on it by calling the setOnClickListener() method.

rollButton.setOnClickListener {
}

As you type, Android Studio may show multiple suggestions. For this case, choose the setOnClickListener {...} option.

Within the curly braces, you put instructions for what should happen when the button is tapped. For now, you'll have your app display a Toast, which is a brief message that appears to the user.

Create a Toast with the text "Dice Rolled!" by calling Toast.makeText().

val toast = Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT)

Then tell the Toast to display itself by calling the show() method.

toast.show()

This is what your updated the MainActivity class looks like; the package and import statements are still at the top of the file:

In their place, create a new variable called resultTextView to store the TextView.

Use findViewById() to find textView in the layout using its ID, and store a reference to it.

val resultTextView: TextView = findViewById(R.id.textView)

Set the text on resultTextView to be "6" in quotations.

resultTextView.text = "6"

This is similar to what you did by setting the text in Attributes, but now it's in your code, so the text needs to be inside double quotation marks. Setting this explicitly means that for now, the TextView always displays 6. You'll add the code to roll the dice and show different values in the next task.

Add the Dice class

Notice that Android Studio underlines numSides with a wavy gray line. (This may take a moment to appear.)

Hover your pointer over numSides, and a popup appears saying Property 'numSides' could be private.

Marking numSides as private will make it only accessible within the Dice class. Since the only code that will be using numSides is inside the Dice class, it's okay to make this argument private for the Dice class. You'll learn more about private versus public variables in the next unit.

Go ahead and make the suggested fix from Android Studio by clicking Make 'numSides' 'private'.

Create a rollDice() method

Now that you've added a Dice class to your app, you'll update MainActivity to use it. To organize your code better, put all the logic about rolling a dice into one function.

Replace the code in the click listener that sets the text to "6" with a call to rollDice().

Run your app. The dice result should change to other values besides 6! Since it is a random number from 1 to 6, the value 6 might appear sometimes, too.

Hooray, you rock!

It's normal for your code to look a little messy after you tweak parts here and there to get your app to work. But before you walk away from your code, you should do some easy cleanup tasks. Then the app will be in good shape and easier to maintain going forward.

These habits are what professional Android developers practice when they write their code.

Android Style Guide

As you work on teams, it's ideal for team members to write code in a similar way, so there's some consistency across the code. That is why Android has a Style Guide for how to write Android code—naming conventions, formatting, and other good practices to follow. Conform to these guidelines when you write Android code: Kotlin Style Guide for Android Developers.

Below are a couple of ways you can adhere to the style guide.

Clean up your code

Condense your code

You can make your code more concise by condensing code into a shorter number of lines. For example, here is the code that sets the click listener on the Button.

rollButton.setOnClickListener {
rollDice()
}

Since the instructions for the click listener are only 1 line long, you can condense the rollDice() method call and the curly braces all onto one line. This is what it looks like. One line instead of three lines!

rollButton.setOnClickListener { rollDice() }

Reformat your code

Now you'll reformat your code to make sure it follows recommended code formatting conventions for Android.

In the MainActivity.kt class, select all the text in the file with the keyboard shortcut Control+A on Windows (or Command+A on Mac). Or you could go to the menu in Android Studio Edit > Select All.

With all the text selected in the file, go to the Android Studio menu Code > Reformat Code or use the keyboard shortcut Ctrl+Alt+L (or Command+Option+L on Mac).

That updates the formatting of your code, which includes whitespace, indentation, and more. You may not see any change, and that's good. Your code was already formatted correctly then!

Comment your code

Add some comments to your code to describe what is happening in the code you wrote. As code gets more complicated, it's also important to note why you wrote the code to work the way you did. If you come back to the code later to make changes, what the code does may still be clear, but you may not remember why you wrote it the way you did.

It is common to add a comment for each class (MainActivity and Dice are the only classes you have in your app) and each method you write. Use the /** and **/ symbols at the beginning and end of your comment to tell the system that this is not code. These lines will be ignored when the system executes your code.

Example of a comment on a class:

/**
* This activity allows the user to roll a dice and view the result
* on the screen.
*/
class MainActivity : AppCompatActivity() {

Within a method, you're free to add comments if that would help the reader of your code. Recall that you can use the // symbol at the start of your comment. Everything after the // symbol on a line is considered a comment.