Your First Kotlin Android App: An App From Scratch

Aug 15 2023 · Kotlin 1.8.20, Android 13, Android Studio Flamingo | 2022.2.1

Part 2: Manage Data in Jetpack Compose

13. Handle a Click Interaction

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 12. Learn About Instances, Data & Functions Next episode: 14. Understand State in Jetpack Compose

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 13. Handle a Click Interaction

At this stage, you’ve added the hit me button to Bullseye but when you tap it, nothing happens. It’s time to add some interactivity to the app!!! Let’s start by making the button print out a text message when you tap it.

If you recall, when you added the button into Bullseye, you just passed an empty block of curly braces for the onClick action which means, when the button is tapped, it wont run any code.

We want to modify this to run a little bit of code.

So click inside the curly braces and hit the return key, then type println all lower case and open and close parentheses. And then inside here you can put whatever you want to print out in quotes.

So I’m going to add in two double quotes. And between them, you’ll just write in “Hello, Android”.

Button(onClick = {
  println("Hello, Android!!!")
}) {
  //...

We could click the run button but instead, I’m going to hit ctrl + R which is a shortcut to run the app in the emulator. Now, go ahead and tap the hit me button!

In earlier versions of Android Studio, you’ll see the print message in the run window. But since Android Studio Flamingo and up, print statements are now just displayed in the Logcat window. So I’ll open it up by clicking on the Logcat tab below.

And now you can see “Hello, Android!!!” printed out whenever we tap the hit me button.

I can tap hit me multiple times and each time I tap the button, I see the message printed out.

println() is an example of a function. A function is like a method, except that it’s not attached to any instance. Not being attached to a class means that you can use it without having to name an instance first.

In Kotlin, any time you see a name that starts with a lowercase letter that’s immediately followed by parentheses, such stringResource() or println() — you’re probably looking at the name of a function or method. Composable functions dont follow this lowercase naming pattern though.

Now, the difference is that methods are preceded by the instance that you’re calling the method on. While functions don’t belong to any instance and simply appear on their own.

Print statements could be helpful while debugging but Android Studio gives a more powerful tool for that: The Logcat Window.

Lets check it out.

Back in the code block for the button, enter the following code below the print statement:

Log.i("Button Click Event", "You clicked the Hit Me Button")

In here, you use the Log class and call its i method. The i method here stands for information and notice I’m using the word “method” this time areound because i is defined inside a class.

The Log class has different types of message channels and info is one of them. The Log class prints the message to the Logcat window. And you can use Log messages in combination with the Logcat window to debug your apps.

Now back to the info method. The first argument is the TAG. This is the message identifier. Normally, when working on larger apps, you use the class name where the log message is printed. But for now you just passed a simple string “Button Click Event.” The second argument is the message you want to print out.

Run your app. Then open up the Logcat window from the button group below. You can see it logging different messages about processes that takes place in your app.

Go ahead and click on the hit me button.

If you look closely, you’ll see the messages from both the print and log statements. The tag for the print statement is System.out while the one from the log statement has the one we passed but that’s not all. If you’re working on a large app, you wont be looking through the logs manually.

In the Logcat window, you have a filter text field and this helps you easily search for logs. I’ll go ahead and search for the tag we used which is “Button Click Event.” As you type in, it instantly filters the logs. And you can see the log message.

Click on the button once again. And you can see the message prints to the logcat window.

The logcat window gives us more features just like the search feature when using log statements.

You can think of the Logcat window as a developer’s best friend. It’s very useful as a debuging tool, which means it’s purpose is to help you figure out what’s going on in your program, and to find the cause of any bugs you may have.

You only see its results in Android Studio while you’re developing the app. If you take your app and ship it to the PlayStore, println() and the Log methods have no effect.

It’s only there to help you out while you’re developing.

As you continue programming, you’ll find yourself using Log statements as an indicator to check that specific pieces of code are being executed, or to check on some value that your program has stored.

In the code you just wrote, you’re using a Log statement to make sure that you run some code when you tap the button.

The fact that pressing Hit me! in your app causes the Log statement to print a message in the Logcat window is a good sign. It means that you’ve proven you can make something happen when the button is tapped.

Congratulations — you’ve just written some interactive code!

But you’re not done yet.

Since this a debugging tool, users never see their results. From their point of view, pressing Hit me! still does nothing. You still have to make the button provide a response that the user can see.

You’ll change up the state of the app from the current UI to one that displays an alert dialog whenever the hit me button is tapped.

We’ll start off by adding data into the GameScreen composable function. Yes, functions can also have data because a function could use it to store some information or a result of a computation. Add in the following code:

var alertIsVisible: Boolean = false

In here, you declared a variable named alertIsVisible. It is a variable simply becasue of the var keyword in its definition. And keywords in Kotlin are just reserved words used by the language to refer to something which means that you can’t name your identifiers with keywords like var. In this case var is used here because we want to store a data where its value can be changed later on.

Also, when you’re making variables like this, it’s a good practice to use camel casing, which is a fancy way of saying you start lowercase, and every time you need a new word, you have the first character of that new word capitalized. Just kind of a coding style thing with Kotlin.

At the end, you tell Kotlin what type of variable this is. So the variable that we’re going to be using here is a Boolean variable, which means it can be one of two things: either true or false.

But if you notice, Android Studio informs us that the type can be omitted since we passed in a boolean value . This means that variable’s type can be inferred by Koltin. This is know as “Type Inference.” But I’ll just leave it in there to serve as a reference when you’re going through the code.

And finally, you set an initial value. Remember that when the app starts up, the alert should not be visible. It’s only when you tap “Hit Me” that the alert should be visible, so, you want this variable to start as false and that’s what we did.

Now that the variable is set up, we want to make the button update that variable when it is tapped.

So down in the onClick lambda of the Button, that is, the function that runs when the user taps the hit me button, is where we want to set alertIsVisible to true. We can remove the Log statement, and then changing the variable is as simple as typing alertIsVisible, then the equals sign, and then true.

alertIsVisible = true

Finally, its time to add the code to display the AlertDialog based on the value of the alertIsVisible variable.

Add in the following code under the last Spacer widget:

if (alertIsVisible) {
  Text("This is an alert")
}

The code block you see here is a conditional statement. Conditional statements lets you execute code blocks based on given conditions. They are very useful in programming because sometimes, you only want a certain code or action to be executed only if a condtion is met. In our case here, we want the alert to be displayed only when the alertIsVisible variable is true.

Conditional statements are the secret behind the flow of most apps. For example in chat apps, you only want to display the typing indicator if the other user is typing…you get the idea? Not to worry, you’ll learn more about conditional statements in the third part of this course.

The conditional statement you used here is the if statement. So if the alert is visible then execute the code block…in this case display the alert dialog. For now, you’ll display a text and when this works, you’ll swap it with an actual AlertDialog.

Alright, let’s try it out. You should expect to see a Text widget which displays “This is an alert” right below the game controls.

Go ahead and run your app.

Ooppss!!! The alert text doesnt show up…our code looks correct so what could be going on?

Let’s use a log statement to see if tapping the button updates the alertIsVisible variable. We know alertIsVisible is set to false by default so lets add in the log statement inside the onClick lambda like so:

Button(onClick = {
  alertIsVisible = true
  Log.i("ALERT VISIBLE?", alertIsVisible.toString()) // New Code
}) {
  //...

We use the toString() method to get the string representation of the alertIsVisible variable. Remember, the second argument of the Log.i() method accepts a string as the message to be displayed and alertIsVisible is a Boolean. And a Boolean is not a string so we use toString() to get the string representation. If we dont do this, passing the wrong argument will cause an error in our code.

Alright, run your app once again. Then open up the Logcat window. Clear up the logs by clicking the bin icon on the left side.

Tap the hit me button once again. You dont see the log statement and this is because of the previous filter we added. Clear that up. And you can see the logs. Now tap the hit me button once again.

You can see that alertIsVisible is set to true when the button is tapped but why does our UI not update to show the alert text? The reason for this bug has to do with something called Jetpack Compose State. Let’s talk about that in the next episode.