Android App Development Tutorial for Beginners - Your First App

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
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
Info
Channel: freeCodeCamp.org
Views: 59,437
Rating: undefined out of 5
Keywords:
Id: FjrKMcnKahY
Channel Id: undefined
Length: 55min 20sec (3320 seconds)
Published: Mon Oct 25 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.