1. Dice Roller App
App Manifest Overview
Activity
setContentView
Linear Layout Documentation
In this exercise, you will add a button to your app the same way we have done in the video.
1. Copy the layout XML code below if you haven’t done so already:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="1" />
</LinearLayout>
2. Add another XML tag for the button:
Make sure you set the text to “Roll” by extracting the string to resources and aligning the button horizontally towards the center of the screen.
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/roll" />
3. Position all views in LinearLayout:
To do so, set the orientation of the LinearLayout to vertical and use layout_gravity to align the elements so they are centered as expected.
android:layout_gravity="center_vertical"
android:orientation="vertical"
If you want to start at this step, you can download this exercise code from: Step.01-Exercise-Adding-the-button.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.01-Solution-Adding-the-button or using this git diff.
A note about the view binding feature (Android Studio 3.6+)
Since Developing Android Apps with Kotlin has launched, a new feature, view binding, has been introduced and is available in Android Studio 3.6 and higher. We don't use view binding because it came out after the course, but it's a feature to be aware of.
View binding replaces findViewById
. View binding generates a binding object for each XML layout. You use this binding object to reference views, using their resource ids as the name:
// Creating a binding object for the main_activity.xml layout
binding = ActivityMainBinding.inflate(layoutInflater)
// Referencing a view with the ID roll_button
binding.rollButton
View binding has the following benefits over findViewById
:
- Type safety -
findViewById
requires you to specify the type of view you expect to be returned. For example, if you accidentally specify that you expect anImageButton
to be returned when the actual type is aButton
, you'll get a ClassCastException. View binding protects you from this type of error because the view is a correctly typed property of the binding. - Null safety -
findViewById
expects an integer parameter, which is meant to be the resource ID of a view. It is possible, though, to pass in any integer as a parameter, including unrelated integers and invalid view ids. If you supply an integer that doesn't match a view resource id in the layout,findViewById
returns null and can cause aNullPointerException
. View binding is null safe because you reference view objects directly and don't look them up by integer IDs.
To learn more about how to use view binding in your app, check out the View Binding documentation and the Accessing Views portion of What's new in Architecture Components (Google I/O'19).
Now it’s your turn to complete this exercise yourself.
In this exercise, you will use findViewById
to get a reference to the button.
1. Set button’s id in the activity_main.xml layout file:
android:id="@+id/roll_button"
2. Use findViewById to get a reference to the button and assign it to an immutable variable called rollButton:
val rollButton: Button = findViewById(R.id.roll_button)
3. (Optional) Dynamically modify the Button view:
Set the button text to "Roll Button"
rollButton.text = "Let's Roll"
In this exercise, you will make your app show a Toast message every time the button is clicked.
1. Make sure that you've completed the steps to findViewById:
You'll need to findViewById
for the button, as described in the last video.
3. Set the OnClickListener for the button:
rollButton.setOnClickListener {
}
4. Make the Toast:
This code will make the rollButton show a Toast message.
rollButton.setOnClickListener {
Toast.makeText(this, "button clicked", Toast.LENGTH_SHORT).show()
}
If you want to start at this step, you can download this exercise code here: Step.02-Exercise-OnClickListener.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.02-Solution-OnClickListener or using this git diff
In this exercise, you will make your app show a random number in the result_text TextView.
1. Assign an id to TextView in the layout:
android:id="@+id/result_text"
2. Remove the Toast and create a method called rollDice:
You can do this by adding the following:
rollButton.setOnClickListener {
rollDice()
}
And then using the keyboard shortcut, you can generate the method in Android Studio:
- Windows/Linux: Alt + Enter
- Mac: Option + Enter
3. Write have the rollDice method to get a random number between 1 and 6:
val randomInt = Random().nextInt(6) + 1
4. Use findViewById to get a reference to the TextView and assign it to an immutable variable called resultText:
val resultText: TextView = findViewById(R.id.result_text)
5. Finally, set the random value that you got above as the text of the TextView:
resultText.text = randomInt.toString()
If you want to start at this step, you can download this exercise code here: Step.03-Exercise-Rolling-the-dice.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.03-Solution-Rolling-the-dice or using this git diff
In this exercise, you will replace the TextView with an ImageView that will show the right drawable based on the random number.
1. Add the dice images to the drawable folder
Add the Dice images file as explained in the previous video.
2. Replace TextView with ImageView and assign empty_dice drawable to it:
<ImageView
android:id="@+id/dice_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/empty_dice" />
3. Replace reference to the TextView with the ImageView:
val diceImage: ImageView = findViewById(R.id.dice_image)
4. Choose the right drawable resource based on the value of randomInt:
val drawableResource = when (randomInt) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
5. Finally, assign the drawableResource from above to diceImage:
diceImage.setImageResource(drawableResource)
If you want to start at this step, you can download this exercise code here: Step.04-Exercise-Adding-the-ImageView.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.04-Solution-Adding-the-ImageView or using this git diff.
Here is additional information on the topic of late initialization if you are curious: late-initialized-properties-and-variables.
Now it’s your turn to complete this exercise yourself.
1. Use lateinit to extract the image view variable:
lateinit var diceImage: ImageView
2. Initialize the image view variable:
diceImage = findViewById(R.id.dice_image)
If you want to start at this step, you can download this exercise code here: Step.05-Exercise-Finding-Views-Efficiently.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.05-Solution-Finding-Views-Efficiently or using this git diff.
For more about namespaces, you can read about XML namespaces here
To learn more about the tools name space in particular, check out the documentation
The full explanation of generated Gradle files can be found here.
Gradle Building
If you're trying to decide what versions to support, you can check out:
- The "help me choose" dialog, which is shown when you're setting up Andorid Studio
- The release notes for each version
- Platform version dashboard
Revise it again.
Now it’s your turn to complete this exercise.
1. Enable the use of support library for vector drawables in build.gradle file (app level):
vectorDrawables.useSupportLibrary = true
2. Use app:srcCompat in the image tag in the layout file:
app:srcCompat="@drawable/empty_dice"
3. You’ll also need to add the namespace to the root of the layout:
xmlns:app="http://schemas.android.com/apk/res-auto"
If you want to start at this step, you can download this exercise code here: Step.06-Exercise-Use-Vector-Drawable-Compat.
You will find plenty of //TODO
comments to help you complete this exercise, and if you get stuck, go back and watch the video again.
Once you’re done, you can check your solution against the solution we’ve provided here Step.06-Solution-Use-Vector-Drawable-Compat or using this git diff.
0 Comments