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. To build. 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. Okay, great. 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. Okay, awesome. 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. That's 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. Awesome. So if this is your first ever entered app,
that's amazing. Congratulations. 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. Bye