Seventy-five percent of all phones are Android phones and seventy-five percent of all Internet users only access the Internet using their phone. So there is a big market for Android apps.
We just published crash course on Android app development on the freeCodeCamp.org YouTube channel. This course is perfect if you are brand new to Android app development.
Rahul Pandey developed this course. Rahul is an Android Lead at Facebook and a lecturer at Stanford University.
In this course you will learn Android development by building a tip calculator. This course assumes no prior experience with Android, and by the end you'll have something an app you could publish.
You will learn how to create the user interface with XML, and how to code the logic using the Kotlin programming language. These are the fundamental building blocks of any modern Android app.
You will also learn how to use the ConstraintLayout for the layout and two event listeners for the app logic. After you enter a base amount and a tip percentage, the app will calculate the tip and total for you. You will also implement a tip percentage animation and a footer to make our app more unique.
Watch the course below or on the freeCodeCamp.org YouTube channel (1-hour watch).
In this beginner's course, you will learn how to create an Android app from Rahul Pandey.
Rahul is an Android engineer at Facebook and a lecture at Stanford University, we're going to build an Android app from the very beginning, we'll start with an empty project and end with something you can actually use, and even publish to the Play Store, we're gonna build a tip calculator, where you can enter in a base amount, tip percentage, and the app will calculate the tip and total amount for you.
We're going to build this app using the kotlin programming language.
So I'm going to assume you have some background in programming.
But if you're new to kotlin, I'll leave a link in the description to a quick 12 minute primer about the language I made.
I'm Rahho, I've been teaching Android on YouTube and off YouTube for a while now.
So when you're ready, let's get into it and build this app together.
There are three things I want to cover in this video.
Number one, I want to walk through the main features of the tip calculator application.
Number two, I will explain the core Android concepts we'll cover while building it.
And third, because I'm keeping the app deliberately, very simple, I also want to call out some of the Android concepts that we won't encounter about building it.
And those will be covered in more sophisticated or complicated Android apps later on.
I mentioned earlier how you could actually go ahead and publish this app on the Google Play Store as soon as he finished, finished the tutorial.
And that's exactly what I did.
So if you want to try out what we're going to build, then feel free to check out the link in the description and download on one of your Android devices.
So let's do a demo of the app so we can get a sense of the main features that we're going to build.
So in this example, I went out for a very lavish solo dinner, and I spent $83.15.
And I'm leaving a pretty generous tip of 24% and the apple automatically compute the tip and total amount.
So just to make the math a little bit easier, why don't we update the base amount to be $100.
And what you can see is, the keyboard that comes up only allows us to input numbers and decimals, which makes sense because we're dealing with currencies here.
And if I'm feeling really happy with the service I received at the meal, I could increase the tip percentage and bring it to the maximum amount to 30%.
And two things happen here.
One is that we dynamically update the tip and total amount computations at 30.
And the sum is 130.
But also, we update the description of that tip percentage.
So went from great to amazing and also became this brighter green color.
On the other hand, if I was really unhappy with the service, I might tip zero.
And we consider that a poor tip.
And you can see how the color got updated to this red color.
And then at the bottom here in the footer, we also have a way to personalize the app so you can say who you who made it or where you're from.
The concepts we cover in the tip calculator are the same concepts that are fundamental to every Android app.
First is creating the UI.
Every app needs a user interface.
And the core component we'll leverage here is a constraint layout, which will contain the other widgets, for example, the TextView, or the seekpart, enter in the tip percentage.
Second, every interesting Android app is going to listen and react to user input.
So we have two ways of inputting data in our app, one is entering in the base amount.
And second is a tip percentage.
And based on that we need to react and update the UI appropriately.
And third, we will barely scratched the surface of styling and animation on Android, I'll show you how to update some of the colors and also show you how to do an animation with the tip description and change its color dynamically.
There's also a lot that we're not going to cover in the tip calculator.
And that's important in order to reduce scope and make this app really quick and simple.
If you're new to Android, first, we're not going to have multiple screens.
Which means that we don't have to deal with things like navigation or the back stack in Android.
And in fact, the single screen that we do have is actually quite simple, because we don't have any kind of list data that we need to manage.
Second, we have nothing to do with networking in the internet.
As soon as you start talking to an API or server, things become quite a bit more complicated because you have to deal with asynchronous programming and managing that data.
And third, we're also not dealing at all with storage, everything it will be local and in memory.
So we're not going to write to a database or to disk or to the cloud anywhere.
And all three of these make the app much simpler to build.
So I'm sure when you build this and you walk into a restaurant, you're going to be super popular because you'll be able to compute the tip dough easily and literally Your name will be on the app.
So I will see you in the next video.
In this video, we're going to start with the brand new enter studio project and layout the views For our tip calculator, in particular, we're going to lay out eight views where the four text views from the left will describe the contents of what is being shown on the right.
The first thing we'll do is create a brand new enter studio project.
So I have in our studio running here, and I'm running arctic fox, but any recent version should do tap on new project.
And I'm going to pick the empty activity template.
These other ones are useful sometimes, but they bring in a lot of cruft into our application, which could be confusing.
So usually, I'll just go with empty activity.
Let's call our application Tippie.
The package name, usually what I'll do is I'll take my domain name or my email address and flip it backwards.
So I'll leave that as is and then pick a location, make sure you have kotlin, select this language.
And I'm going to pick minimum SDK version of API 21.
Now I'll tap on finish.
And the very first thing I like to do whenever I have a brand new project is simply try and run the starter code.
Because if we can't even run the starter code, then something's already gone wrong.
Let's make sure that we're at a known good place before we start writing any code.
When we create a new project in our studio will take some time to set everything up.
To run our application, we can go to the drop down in the menu and choose to deploy our app either to an emulator or a physical device.
So I'm going to choose pixel two API 29, which is an emulator I created from before, hit that green triangle to boot up our emulator if it doesn't already exist, and then build and deploy our project to this emulator.
And you'll see the status at the bottom of Android Studio to see the current progress.
This might take a minute or two.
But when it's done, the app will get automatically sent to the device and brought to the foreground.
So all we need to do is wait until we see some action on the emulator.
This looks promising.
We are seeing an application called to be so open emulator with the text of hello world, which is a default for an empty project.
And this gives us confidence that we are able to successfully run the basic project.
Let's come into inner studio and spend a quick minute talking about the starter files.
And actually, it's quite simple because there are only two files that we're going to be concerned with main activity dot kotlin and activity main dot XML, you can think of an activity in Android terminology as representing one screen.
So with the project that we have, right now, we only have one screen.
And that's referred to as the main activity or the main screen.
And that's the business logic that we're defining right here in this file called main activity.
In particular, the starter code gives us one function or one method that is already being overridden.
And that's called onCreate, to the Android system will automatically invoke or call this function when our application is starting up when it's creating our screen.
And the important line here is line nine setcontentview r dot layout activity main.
So R stands for resources.
So what we're saying here is that the content or the UI of our screen should be the layout file in resources, defined at activity main dot XML.
And indeed, if we jump to the definition of this, we can see that goes directly to activity main dot XML.
So I'm going to minimize the project tool window over here to give a give ourselves more room.
And that's also minimize the attributes pane.
So here's exactly what we're seeing in the application, just a blank canvas with HelloWorld.
And in particular, if you look at the component tree over here, it might be minimized for you.
But you can expand it by tapping over here, we can see the parent element is something called a constraint layout.
And it has exactly one child called a TextView, or a label.
And that has an attribute which has value hello world.
And that's how we're seeing the Hello World text in our running application.
In this video, we're going to spend all our time in activity main dot XML, because we're only concerned right now with constructing the UI for our application.
And in particular, here's how we want to end we're gonna have eight components in the screen.
On the left, we have four different text views, you can think of a text, you'd like a label, which isn't editable by the user.
On the right, we have the actual components being described by the TextView.
So we have an edit text at the top, which allows the user to enter in a bill amount, we have a seek bar, which allows the user to enter in a tip percentage, and then two more texts use at the bottom for the tip and total amount.
There's one more thing I want to call out before we start constructing our layout, which is that there are multiple perspectives of our UI, what we're looking at by default is a design preview, which is what will actually show up on your emulator or device.
But you can also drop down into the code tab, which is the actual underlying XML.
So you can see how we have the constraint layout and then one child view the text view same as design.
Split means you look at both.
And most of our time is going to be spent looking at design preview.
And what we can do is go into the palette and drag and drop different components like a text view or edit text that we want.
And again, that will be represented in the code tab.
So just keep that in mind that there is a one to one correspondence between whatever changes you make in the design preview and the underlying XML.
So for now, let's go back to design, delete whatever components we have, so we have single constraint layout with no children.
The documentation describes constraint layout as a way to create large and complex layouts with the flat view hierarchy.
We're able to describe the relationship between sibling views and parent layouts through a set of constraints that we define.
And that allows the inner system to gracefully layout our UI across phones or tablets of multiple sizes.
And the important thing here is no nested view groups.
On Android, if you have a very deeply nested view hierarchy, that leads to a lot of performance degradation and something that we call jank, or UI lag.
And so the constraint layout allows us to create complex views without having nested view groups.
Coming back to the tip calculator project, we're going to lay out all eight views on screen here in a single parent constraint layout, there will be no nested view groups, which is as good as we can get there, no relative layout or linear layouts inside of our parent constraint layout.
So even if you've never worked with the constraint layout before, take a moment right now to think about how might you position the views on screen here relative to one another, such that we can describe it in a flat view hierarchy.
Back in Android Studio, the first thing we'll do is drag out a TextView representing the top left component of our screen, which is the TextView representing the base table.
The first thing I do whenever I drag out any component is update the ID to be something more meaningful.
So I'll call this TV base label and then update the text to be base.
And what you'll notice here is that Android Studio is complaining that this TextView is missing constraints.
So it only has designed time positions, it'll jump to position 00, which is the top left of the screen at runtime unless we add constraints.
And this is the whole point of the constraint layout, we have to constrain every component vertically and horizontally.
So vertically, what we'll do is drag this top anchor point of the TV based label and drag it to the top of the screen.
And then in the attributes tab, we will specify the margin of how far away we want it from the top of the screen, and I'm going to say 48 on the top.
Similarly, we want to specify a left margin, so we'll drag the left anchor point and drag it to the parent and specify this to be 32 dP away from the left end of the screen.
So now you can see the error went away, we're going to do the same process now for the other three texts use on the left side of the screen.
Starting with the one right below the base label is a TV tip percent label.
Author the text here to be 24%.
The TextView below that will be the TV tip label.
The text will be tip.
And then finally we'll have the TV total label.
And the text here will be total.
So we have the same issue where we have to constrain all of these horizontally and vertically, vertically, what we'll do is take the top anchor point for each TextView and drag it to the component above it.
And we'll specify a margin of 32 dP which means that each text you should live 32 pixels at 32 dP below the text you above it, that will drag the top anchor point and drag it to the bottom anchor point of the text above it.
And again, do the same thing 32 dP constrain each of these views vertically.
Now how about horizontally, if we go back to the desired end state, what you'll notice is that if we draw a vertical line here, all of the components on the left side, they will all be aligned to the right end of that top text you this TV base table.
That is how we want to constrain them horizontally.
And we could actually do this in the Design tab, you could say align and then align the right edges.
But I'd like to show you how to do this in the code tab.
So if I open up the code tab, like we talked about, every change you make in the Design tab has a corresponding change in the code tab.
So right now we have four textures and that's exactly what we can see here we have 1234, like we talked about, there's right now an error in that we are not constraining these horizontally.
That's why we have this red underline.
The vertical constraint is what you can see here.
So what we're communicating with this line is at the top of the TV tip percent label should be exactly equal to the bottom of the TV basic what is a TextView above it, along with a margin of 32 dP which means you want it to be 32 pixels below the component above it.
So similarly, what we want to do is specify that the end of this component, the TV tip percent label should be equal to the end of the TV based label.
And we want this to be applied to each of the components on the left side So with that, you can see how that error went away.
And if we go back to the Design tab, you can see how everything is now aligned.
One more thing I want to call out here is that the tools namespace is only used for the purpose of rendering the design preview.
Because we have now fully constrained each of these views horizontally and vertically, we don't actually need this anymore.
So I'm going to select each of these and delete it.
And one more thing is I'm pretty big on having a consistent style and ordering of the different attribute names.
So for example, here we have the ending angle bracket on the same line or new line.
And to fix that automatically for us, I can tap double shift, and then just search for re format.
And there's a shortcut for re formatting the code.
If I do that, then you can see how Android Studio helped us to fix it up across the whole file, which I like a lot more.
Right, so let's go back into the Design tab.
And before we move on to the component on the right side of the screen, one thing I want to do just a few quick design tweaks.
First, I want to make the text a little bit bigger here.
So I'm going to make the text appearance medium, you can see how that made it bigger.
And then this TV tip present label is a bit unique, because it's representing the value of what to present the user actually chose.
So to indicate that it's a little bit different from the others, I'm going to make the text bold here.
Cool, I like that.
Now let's think about the four components on the right end of the screen.
This one is going to be edit text, the below that we have seekbar.
And then below that we have two text views.
So let's drag out a edit text.
And the one we'll drag is the one which says a number of decimal.
And the difference between all these different edit text is actually quite simple.
It's simply the input type.
Because we're dealing with the currency, we want numbers and decimals in ours.
Below this, we are going to have a seek bar.
And then below that, we're going to drag out to TextView.
Alright, let's update the IDS here to be something more sensible.
So this is going to be called at base amount.
Next we have the seekbar tip.
Then we have TV tip amount.
And then finally we have the TV total amount.
Let's update the text here to be 103 dot 11.
And this one, I think we said 1996.
Let's do some design tweaks before we position these elements.
So these bottom textures, these is the most important part of the whole app.
So I'm going to make the text large.
The seekbar, I'm going to specify a hard coded width of 200 dP to make it a little bit wider.
And then also there's an attribute here called Max, which is the maximum amount that seekbar will hold.
And that'll be 30.
Because we only allow up to 30%.
For the edit text, I'm going to set the EMAS to be eight, which means how many characters wide how many characters wide will this edit text be and eight is sufficient for us, I'm going to increase the text size to be 24 SP.
And then finally, I'm going to add a hint here or a placeholder, which is the bill amount to the user knows what this edit text is for.
Now let's think about how to position these.
So vertically, the bottom two texts, you should be aligned vertically, so I'm going to select both of them and then align the vertical centers.
And similarly for the ones above those.
And then similarly for the tip percent and the seekbar.
And you can see how in the Design tab, we're actually able to see this nice preview of the constraints which are added.
For the bill amount.
Let's think about how to constrain it horizontally, it'll be 32 dP away from the corresponding text you on the left side.
And horizontally, all the other components on the right side, these bottom three should be aligned to the left end of the bill amount edittext, there must select all of them, and I'm going to specify the left edges should all be aligned.
That looks good.
The only thing we have to do now is if we hover over here, we are missing a vertical constraint on the edit text.
So to do that, I'm going to go into the code tab.
Here's the edit text at base amount.
And the way we'll communicate the vertical positioning is by considering the top of this element to the top of the top left view which is a TV base table and similarly The bottom of this view should also be the bottom of the TV base table.
So it'll be right in the middle vertically.
So if you go back to the Design tab, you can see that now the errors have gone away.
And you can see visually what these constraints look like.
If you go back to the Design tab, again, we don't need this tools namespace anymore, because we are fully constraining everything.
Let's reformat the code really fast.
And then one more thing I want to do is, even though this is not needed, for the purposes of running the program, just for the sake of developer information, I'd like to label these with a comment.
These are the views on the left side.
And then after for TextView, starting with the edit text, these are the views on the right side.
That's right to see what this looks like.
Like we expect this is pretty much exactly mirroring what we see in the design preview.
The only thing that I want to fix up here or improve is that it's a little bit weird that we already have values for the tip and total amount, even though the user hasn't actually entered anything.
And that's exactly what the purpose of the tools namespace is that we talked about earlier.
So what I'll do is select the corresponding text view.
And rather than having a text here, I'm going to scroll down.
I'm going to move this over into the wrench text area.
And that's the tools namespace.
So I'm going to move these over into the tools text.
And then finally, the same thing over here.
Just to show you what that did, if we go back to the code tab, if you look at the TV tip percent label now instead of having the Android text attribute is now the tools text attribute.
If we run the app one last time, let's see the impact this has on the initial layout.
Awesome, this looks pretty good.
Hopefully this video gave you a good sense of the power of the constraint layout.
One thing I can show you just to demonstrate what we've done is that with these eight views on screen, they're all located instead of a single parent.
And if I drag out that top left TextView everything moves according to that, which is a really nice way of relatively constraining all the views to each other.
So the job in the next video is actually to hook up the business logic in the main activity, so we can react to the input and compute the tip in total.
See you in the next video.
In the last video, we laid out the eight views on screen for our tip calculator application.
In this video, we want to add the business logic to actually make our app interactive, we'd like to be able to do is when the user scrubs on the seat bar, we want to update the tip percent label.
And when they enter in a base amount, then we want to take that value and then compute the tip in total amount.
In particular, you'll notice that there is no Submit button.
So as soon as the user changes the base amount or the tip percent, we want to dynamically compute the tip and total amount when anything changes.
So as a first exercise, what I want to be able to do is as soon as the user changes the value on a seekbar, I want to be able to update the percent label.
So in order to do the first thing we'll do is getting a reference to the views in the screen that we actually need to be able to read data from or modify.
And there are actually five different widgets on screen that we care about the tip percent label and then all for the components on the right side of the screen.
So in in our studio, the way we'll do this is declare a bunch of variables up here for each of the components.
So for example, we have the edit text, that'll be at base amount.
And the type of this is going to be a type edit text.
But don't worry too much about the syntax here.
If it's confusing, all we're saying is a private variable.
It's a late initialization because we're going to initialize it inside of the onCreate method and not in the constructor, which is why it's late initialization is a variable and that we're calling it at base mount the convention I follow that the name of the variable is exactly equal to the name of the ID.
So now in the onCreate.
After the set content view, we are going to say at base mount find view by ID et base amount.
And we're going to repeat this now for the other four components on the screen.
So we have a seekbar tip.
And that type here is seekbar.
And then we have TV tip percent.
That's going to be text to you.
And then we have two more texts for us.
One is TV tip amount, and the other is TV total amount.
Now I'll just pull out references to all these inside of onCreate And finally we have the total amount.
So going back to our objective, the first thing you want to do is when the user scrubs on the seat bar, we want to be notified of changes of that user input, and then update the TV tip percent label to indicate that.
So actually, let me update the name of the variable here just be TV 2% label for consistency.
And the way we get notified of changes on the seat bar is by adding a listener on it, it'll say seek bar tip dot set on seek bar change listener.
And now we need to tell the entertainer what should happen when the seat bar has changed.
And the syntax here is we're going to say object, seek bar.on, seekbar, change listener.
And then we're going to define this class inside here.
And enter today will help us implement this, you'll have this red underline under object to tap on that red light bulb and tap on implement members.
There are three methods that we have to override in order to comply with the definition of this on seekbar, change listener.
And NRC will help us with that.
And don't worry too much.
Again, the syntax is confusing.
The details here are that we are defining an anonymous class which implements this interface.
So if I go to the definition here, you can see that this is a public interface, which has those three methods exactly that we have overridden.
And now it's our job to tell the system what should be happening when each of these methods are called.
And actually, we don't really care about on start tracking touch or on stop tracking touch.
So I'm going to remove the two dues here, and let's leave it empty implementation.
Before we update the UI, let's first add a log statement in Android to more easily figure out what's going on.
So I'll right logged on i and this is a method that takes in two parameters.
The first one is a string, which I'll call tack, I'll define later.
And the second one is also a string, which is a message or a log statement.
And I'll say on progress changed, which is a method name, along with the progress, which is a current value of the seekbar.
So let's define this tag, I'm going to go up to the top of the class and define a private const Val tag.
And the convention here is that whenever you have any kind of logging, the tag is typically going to be the class name.
Alright, let's try it.
So the idea here is that every time the progress has changed on the seat bar, which means the user is scrubbing, we will print out the current value shown in logcat, which is where the logs output it.
So open up logcat.
Open up the emulator.
And the logs that we care about are the ones from only our application, which is calm, calm, rk Pandey Tippi and we also only care about info level logs because that is what log.io represents info level logs.
We also only care about logs, which have this particular tag, which is main activity.
So let's add main activity as a filter.
And here as we change the seat bar, you can see how we get one line of logcat output, and it represents exactly what is the current indicator of the seat bar showing.
So if we go all the way up to the maximum, we see 30 as we expect, and if we come all the way back down, we go to zero.
So now let's update the UI.
And in particular, we want to update the TV tip percent label to indicate the current progress of the seekbar.
So we'll say TV 2%, label the text attribute of that, we will set that equal to the progress.
But actually, we want the progress to be represented as a string, not an int.
And also we want to concatenate a percent sign after it.
So we'll say dollar sign progress, which is how we do string interpolation in kotlin.
Similar that we did in a log statement, and then add a percent sign at the end.
Let's try it.
So as we scrub on the seekbar, you can see how the TV tip percent label does get updated in lockstep with the current progress of the seekbar, which is great.
One improvement here though, is that initially, we are not indicating any tip percent in the label.
And so to fix that, let's define one more constant, which we'll call initial tip present.
So we'll have a private const Val initial tip present, and we'll set that equal to 15.
So initially, the default tip is going to be 15%.
So with that diviner the constant before we do anything in the listener, great in the onCreate method, will they seek bar tip dot progress is equal to initial tip percent.
And we also want to update the label appropriately.
So we'll say TV tip percent label dot text is equal to initial tip percent, with the percent sign after.
Now when we run the app, we should see instead of the blank 2% label, we should see 15% like we do and the progress bar indicator is exactly in the middle of the width of the whole seat bar.
Next, similar to how we are able to react to changes in the seat bar, we also want to be able to react to changes In the edit text, so there's a analogous method on the ET base mount we'll call add text change listener.
And the syntax is similar, we pass in an object here, which is an anonymous class is an implementation of the text watcher.
And we'll have Enter to help us once again, there are some methods that we have to override.
So I'm going to tap on that red light bulb and implement the members three, override all them.
And then similar to before, the only thing that we care about is after text change, I'm going to go ahead and delete the body of implementation here.
Just to get a better understanding of what's happening here.
Again, let's add a log statement after text changed.
dollar sign ups.
Alright, let's try it.
So dollar sign s is the parameter passed in.
And that is actually what the user is typing at that moment.
Run this, let's open up logcat once again.
Alright, so like before, if I modify the seek bar, you can see that it is changing appropriately.
And then if I add the value into the edit text, you can see 800 it is being updated appropriately in log.
Two quick notes.
First, I sometimes see students will get tripped up when they invoke functions in kotlin.
The MSG that you're seeing when we call log into it is a hint from energy about what that parameter represents.
So if you actually type MSG, that will lead to a compile error.
So let's make sure you don't do this.
Second, I want to demystify what the object keyword means.
So the object expressions like we're using twice so far, are examples of how to create anonymous classes, which are one time use classes that are commonly used to implement interfaces.
So we have both text watcher and on seekbar change listener as interfaces defined by the Android system.
And these methods that we're overriding will automatically be invoked for us when the user takes the appropriate action on the underlying edit text or seekbar.
So now we have all the ingredients in place to actually make this app functional.
Whenever the Edit Text changes, I'm going to call a method called compute, tip, and total.
And this is actually what will take the values from the edit text and seekbar and then update the tip and total amount appropriately.
So this method doesn't exist yet.
But again, let's leverage the utility of Android Studio and have to create this function for us inside of main activity.
And there are a couple things that have to happen in this method.
First, we want to get the value of the basic tip present.
Second, we'd like to compute the tip in total.
And third, we need to update the UI to show those values.
So to get the value of the basic tip, that's pretty straightforward, we just look at the edit text at base amount, grab the text, and then call to string on it.
And then on a string, we know it's going to be a currency like a decimal, so we'll call to double on it, in order to turn it into a number that we can work with.
And we'll call this base amount.
And then similarly, for the 2%, we want to get the value of the progress on the seat bar, this attribute called progress, and that'll be saved in a variable that I'm going to call tip percent.
Quite Next, we want to compute the tip and total amount.
So the tip amount is going to be the base amount, times the tip percent divided by 100.
So for example, if the base amount is $100, I went for $100 meal, and the tip percent is 20, then I expect the tip amount to be $20.
So that'd be 20 divided by 100 is 20% times 100.
And that gives me $20.
So that'll be tip amount.
And then we have the total amount, and the total amount is simply going to be the base amount, plus the tip amount.
Okay, finally, we need to update the UI.
And again, this turns out to be pretty straightforward, because we have a reference to the two text views which show the tip and total amount, which is TV tip amount, and we're going to set the text attribute there to be tip amount.
And this is going to throw an error because tip amount is a number it's a double right, but we actually require something called a car sequence.
And to give it a car sequence, we can just call to string on this.
And then similarly, we call we need to say TV total amount is that the text attribute here to be the total amount to string.
And this should be a plus sign.
Wait, this is the whole brain of our application.
So if we run this, then what we're doing is anytime that the edit text value has changed, we're going to call this method and we should be updating the UI To have the correct amount for the tip and total amount, right, so we have 15%.
For the tip, if I add in $100 here, then you do see immediately we get the correct tip and total computation.
And we would like to have the same logic get executed if I change the seat bar, the 2%.
And that turns out to be really easy, because we've abstracted all the logic away into this method.
So I'm going to call compute tip and total, right here in on progress changed.
Alright, so if you try this now, we should have a pretty functional app.
So similar to before, if I put in 100.
Here, we do correctly compute 115.
And if I change the percent, you can see it does appropriately updated.
Alright, so this is working actually pretty well.
But there are two things that I think are incorrect or could be improved.
But just take a moment right now think about what are two improvements that you could do to the app that we have right now try playing around with it, see if you can identify any issues.
Okay, so the first improvement that we can make is actually a bug.
So notice what will happen now if I Backspace on the base amount, so that there's nothing there, so you can see the app actually crashed.
So if we look at logcat, let's take a look at what actually was the error.
So I'm going to scroll up to the very top of the stack trace.
And you can see here we have a number format exception.
This is the important part, there's an empty string.
And and the stack trace tells us exactly where the issue happened is a main activity line 58.
And so the issue that's happening is that when the edit text has an empty value, then it doesn't make sense to try and convert an empty string into a double.
The very first thing we shouldn't be doing here is actually checking if at base amount done dot txt, if that is empty, then we need to do an earlier turn.
Additionally, we should be clearing out the values of the TV tip and total amount.
Because if the edit text is empty, that means there's nothing to tap on.
And we should be showing nothing for those two textures, then we call return, so that none of the rest of the function will get executed.
The second improvement we'll make is about formatting the output of the tip and total amount.
So it's not that noticeable when we enter in 100 for the base amount.
But if we add in 100.9, then you can see the total amount becomes very long and unwieldy.
Because we're dealing with currency, we should really be mandating that there are exactly two decimal points in both a tip and total amount.
And the way we'll do that is right here, instead of just calling to string, we want to format the string before we put it into the TextView.
So the way we do that is by using this format method.
So we define the format like this percent.to F, which means we only want two numbers after after the decimal point dot format.
And we pass in the tip amount.
And then similarly for the total amount, a percent dot two f format.
Let's try it.
For hopefully now, in this scenario, we should actually end up with 116.04 instead of this very long decimal that had happened 100 right away, you can see instead of only having one decimal point now we have two.
And the true test is when I type in 100.9.
Now, the display of this is way better, we have 116.04 rather than that huge decimal which becomes unreadable.
So at this point, we have a very functional app, what we've done is gotten references to the relevant views on layout, and then added listeners to the seekbar into the Edit Text because there's no Submit button.
Anytime there's any change in the seekbar or the edit text, we are dynamically computing the tip and total amount and updating the views appropriately in this compute tip a total amount.
So in the next video, what I want to show you is some style improvements along with a way to personalize it and add a really cool animation.
So I'll see you in the next one.
At this point, we're done with the implementation of our tip calculator.
In this video, our goal is to add some color animation and personalization into the app.
So we'll start off with the footer at the bottom.
A lot of apps or websites have this where it says you know made with love in California or made with love by this person.
So we're gonna start off by adding a text at the bottom of the screen.
So let's go into enter studio, open up the activity main dot XML and scroll down to the bottom and we're going to drag out one TextView here.
Let's give it an ID of TV footer.
And then the text will be made with love by raw and of course you can personalize however you want to constrain it.
We're going to have this horizontally be in the center of the screen.
So we're gonna add a left and right Straight to make it centered, and then we're gonna make it 32 dP from the bottom of the screen.
I also want to add a couple different style tweaks here.
First is all caps, I want to make everything here capitalized.
And I want to change the font to be sans serif, condensed, slight.
And then finally, I want to make this a little bit larger text, appearance, medium weight.
And finally, I want to change the love word with the emoji.
And you can either add this to your keyboard, or another way to do this is if you Google for heart emoji, then the first result that comes up, gives me an option here to copy and paste the emoji.
paste that in.
And it looks a little bit weird in the preview, but it does show up properly when you render it in the design.
And if we check it out in the app.
Awesome, that looks pretty good.
The next thing I like to do is a bit the color scheme.
So we move away from these default status bar color color primary in this background white.
So let me explain where these colors are coming from.
There's one very important file that must exist in every single Android app.
And that's called the Android manifest file.
So if we open that up, then this file describes all the different components of your application, the permissions, for example, if your app needs internet permission, and much more.
And the important line for us is right here on line 11, where we're describing the theme of our application, and this is a file that automatically gets created for us when we create the empty project.
So I'm going to jump to the definition here.
And you'll see you have two different files here, one for normal theme and one for the night theme.
And the one that we're currently looking at is normal, I'm gonna open that up.
And this is where we're getting the colors for the default application that we have.
So in order to update the colors, we're going to have to define new colors and then replace them here, we can take a look at where this file lives by hitting this option, select Open File, and we can see that it lives inside of resources, values, and themes directory.
And the colors are also defined inside of colors XML in the values directory.
And each of the colors is defined as a hexadecimal value, purple, 500, and so on.
So our job is let's figure out what colors we want, and then add them here.
And then we'll reference them inside of the themes XML file.
So in order to figure out what colors you want, there's a couple different options, I'll show you what I typically do if you go to color.adobe.com.
There's this really nice tool where you figure out what kind of color scheme you want.
So there's a couple different options here, you can pick the color harmony rule, analogous monochrome chromatic triad, and so on.
Once you're happy with something, then you can scroll down and grab the hexadecimal values here.
So I did this exercise already.
And here are the colors I came up with, I'm going to have one which is called primary blue, darker blue and background blue.
So let's go ahead into the colors XML and define these for the first one is going to be called primary blue now has this value.
The next one is background blue, or the next one's a darker blue.
And then finally, we have background blue.
So now in themes XML, I updated the color primary to be primary blue.
And then I updated the primary variant to be darker blue, and that's gonna be the color of the status bar.
And then finally, in order to have a background color on the whole app, I'm going to add one more attribute here, which is called background color, Android color background.
And that is going to be the background blue that we have.
Let's try it.
Awesome, that looks great.
So we're getting very close now, to the desired end state, we have the footer, and we have the customized color.
The last thing I want to talk about is this animation on the tip description.
And here's actually what this looks like.
As the user is scrubbing, we will dynamically update the color of that word that's used to describe the current tip percentage, and it'll go from Red if it's a very bad tip to a really bright green if it's really good tip.
Not only that, but we're also going to be changing that word or that adjective used to describe the tip percentage.
So it gives the user some really nice interactive feedback about what kind of tip they're leaving.
Alright, so the first thing we'll do is just added text you need the seek bar and increase the vertical distance between these two texts.
So close out these other editor windows because we don't need to look at them again.
In activity main.
What we'll do is first increase the distance between the 24% which is the 2% label and the TV tip label.
Let's increase the margin here to be 56 Next, let's drag out one more text you.
And we'll call this TV tip description.
And then the text should be empty, because that will depend on the initial tip percent, which is set programmatically.
But to get a better sense of what this might look like, we are going to use a tools namespace and to say acceptable here.
That looks good.
And now we need to position this horizontally and vertically.
So vertically, it's going to be right below the seek bar tip bar, and we'll add a margin here of maybe eight dp.
And then we want these two to be horizontally aligned.
So horizontal centers, great.
And you can see how it added the left and right constraints.
So it'll be right in the middle.
And you can see the error also went away.
So now back in MainActivity, we need to get a reference to that TextView.
So let's say the ID here was TV tip description.
So when I say TV tip description, get a reference to it here.
And every time the C part is changed, that is where we have the potential now, to update the language on that text, you want to have one more method here called update tip description.
And let's have Enter to help us to create this because this method doesn't exist yet.
And one thing we'll do actually is as a parameter into the update tips, description method, I'd like to pass in the progress and progress.
And again, energy video can now help us to add this as a parameter into the function that we have defined.
The tap that red light bulb, and have Enter to help us to add the parameter and all I did here is added a parameter.
And instead of calling it progress, I'm going to call it tip percent.
And it's I've typed in.
So now the idea is that based on the value of tip percent, we'd like to be able to say TV tip description dot txt, and we'd like to be able to set it to be something like good.
And of course, this good will change based on the value.
And the construct in kotlin.
To be able to decide a value of something based on a set of conditionals is called when which is similar to a switch in Java.
So I'm going to save our tip description is equal to when and then depending on the value of 2% will take certain action.
So if tip description, if 10% is between zero and nine, then the string should be poor.
If it's between 10 and 14, we'll call it acceptable 15 and 19, it'll be good.
And when it's between 20 and 24.
It'll be great.
And there should be one extra period in here.
And finally, anything else meaning that the value is above 24 then we will say amazing.
And so now instead of using good here, we will say tip description.
And finally before we test this out one more thing I want to do is at the very beginning, when we are setting up our screen, which is you know in the onCreate method, as soon as we get all the references to each of the views, we also would like to call that method update tip description right here with the initial tip percent just so that language is always going to be in sync with what we start out with.
Let's try it.
So now hopefully we should see a text you right underneath the seekbar and the text on in that text you should change according to what we have selected through the seekbar.
Okay, this looks promising already because initially the 2% is 15, which means we fall into this branch of the wine statement and that means that the value should be good.
And then if we bring it down to zero, we get poor and if we go all the way up, we should get amazing which we do.
One quick thing want to do is back in activity main.
I want to set the font weight of this to be bold.
The textile should be bold to make it stand out a little bit more.
Finally, the last thing I want to show is this interactive color animation where if the user picks a very good tip we show bright green and if the user picks a bad dip, then we show a red color indicating something went wrong.
Coming back into Android Studio in minute tivity kotlin update tip description is where we're going to add the logic for updating the color based on the tip percent.
The question is how do we dynamically compute a color based Based on an integer, the way we'll do this is through a concept called interpolation, which is actually a fancy word for something which is conceptually quite simple.
If I tell you I'm running 100 miles, and I'm 75% of the way done, then you would tell me that I'm roughly at the 75 mile mark.
And what you're doing in your head is linear interpolation, you're assuming I'm going at a constant speed starting at zero ending at 100.
Therefore, I'm at 75 miles, the same thing is exactly applying here.
Every color can be represented as integer.
So if I'm tipping 20%, then we're two thirds of the way between the very worst color and the very best color, which are two integers.
And all we need to do is some simple math in order to compute what exactly that color value is, for the tip description.
The first thing we'll do is define the color for the worst invest tip.
So open up colors, XML, and let's add in color words tip color, best tip and I picked a red and green color like we talked about, we're going to paste these values in for color worse and color best.
So we have these defined.
And now our job is simply to do some math at zero, we should show worst tip at 30, we should show the best tip and everything else is some value in between.
and this turns out to be so common that Android actually has something called a RGB evaluator to help with this, where we represent colors as integer values.
A stands for alpha, RGB is red, green, blue, and it will help compute the color for us.
So coming back into main activity, we're going to define a color.
And that will be coming from argb evaluator dot evaluate.
And then this takes in three parameters.
One is the fraction of where are we on this progress bar between zero and 32nd is a start value, which is the very worst color and the end value is the best color.
So the fraction is simply going to be the tip percent, which is the perimeter pass 10 divided by the maximum amount of tip which is 30.
And that's going to be seapark tip dot max.
Next, we need to get the very worst color.
And the way we'll do that is context compat dot get color pass in this which is referring to the context and then the actual color that we just defined in the colors XML, which is color first.
And then finally, we're going to provide the best color here.
One issue you'll notice is that there's a type mismatch, we require a float, but we found integer.
So by default, because both the numerator and denominator are integers, we're gonna do some sort of truncation, which we don't want.
So the way to handle this is to cast one of the numerator or denominator to a float value.
And that will resolve that.
So now we have this color, all we need to do is set the color on the tip description text, set text color, with the color.
And finally before before we try this, we need to cast the result of the evaluate function call to be an integer, because we know the values we're computing between are integers, so the color should be an int.
And now we should be able to compile and run this just fine.
So two things should happen now.
One is we should bold the text.
And second, there should be a color applied immediately.
And based on what present we pick, it should adapt as well.
Right, this looks good.
So initially, we have a color right in between the green and red.
And if I go all the way down to zero, you can see how it changes to red.
And if I scrub upward to the best tip, which is 30, you can see how it slowly transforms from red to green.
I like that a lot just because it feels much more interactive and dynamic now compared to what we had before.
Alright, so let's give it one last try.
We're going to put in $9 here for the bill.
And then as I scrub, you can see how everything updates appropriately.
If I Backspace, there's no crash, I can enter in another amount.
And everything works just as we expect.
So if this is your first ever entered app, that's amazing.
Let me know in a comment.
The reason I really liked the tip calculator, there's so many ways you can extend this basic project that we have to make it more interesting.
So a couple ideas I had number one, you could split the bill by n people.
So you could imagine that you go out to dinner with the number of people you add in three or four and then you should divide that total amount by three or four in order to make it easy for everyone to pay a certain amount.
Second, you could add a button or some sort of component which allows the user to round the final amount up or down.
So there's no need to deal with change.
And of course, there's a lot more that you could do in terms of design or color updates.
So what I recommend now is complete any number of extensions, other ones that we talked about, or something that you came up with on your own, and then you can more or less publish exactly what you have on the Play Store.
I won't walk through that here, but I'll leave a video in the description where I talk about how to do that and I hope that you use This tip calculator as a starting point in your journey as an Android developer and you build many more apps in the future.
If you enjoyed this, please drop a like and comment.
We'd love to hear from you.
Thanks so much for watching and I will see you in the next one.