Going Back into Styles.xml: Defining the Base Application Theme
The style app theme defines the base application theme and can be customized here. One property called radio button style is added to this style, which references a custom radio button style. Adding this new style should update all six order buttons to include it.
If we've done the job correctly, all six order buttons should now display this new style. This change is necessary for our application's overall appearance and consistency.
Design Improvement: Aligning with the Demo App
To align the project with the original demo app, a design improvement is made to update the color scheme of the action bar. The color primary dark is set to be a slightly darker gray, and both colors are now referenced in the main activity. Additionally, a margin top of 8dp is added to the SparkVue in the Activity Main to further enhance its appearance.
With these changes, the action bar becomes less noticeable, allowing the Spark Vue and the metric being displayed to take center stage. Finally, the text shown in the action bar is updated to "Code 19 cases per day" to provide a better understanding of what's being displayed.
Conclusion
The COVID-19 tracking app project has come to an end with this final video. This article will serve as a comprehensive guide for building and customizing this application. By following along with each step, developers can create their own version of the Robinhood-style coronavirus tracking app using Retrofit, Spark, Ticker, and Nice Spinner libraries.
The app demonstrates how to fetch data from an API, display it in a Spark line chart, animate text changes, and implement a better-looking dropdown menu. The project also covers implementing local databases and caching data for offline access, which would be ideal for an app that only updates once per day.
Extensions Beyond the Original Project
One potential extension is to add additional state data from different countries, such as China or India. Another idea could be to show cumulative data from the first COVID-19 case up until today, rather than just the delta per day.
Implementing a network request system that retrieves data only when necessary and caching it in a local database would also enhance the app's performance. By exploring these ideas, developers can further improve and customize their own version of the COVID-19 tracking app.
API Reference: Kobit Tracking Project
The Kobit tracking project is an API that provides all the data for our application. This API allows us to fetch the latest COVID-19 case numbers and state data.
Tutorials on building a full-fledged COVID-19 tracking app will cover how to use Retrofit for making API requests, as well as libraries such as Spark, Ticker, and Nice Spinner.
GitHub Repository
The GitHub repository for this project is available for developers who want to build upon it. This includes source code, tutorials, and any additional resources needed to complete the project.
Questions and Support
Developers with questions or need further assistance can feel free to reach out in the comments section. The author will be happy to help as much as possible.
"WEBVTTKind: captionsLanguage: enhey free code camp we're going to build a coronavirus tracking app and we'll do it in the style of a really popular stock trading app called robinhood we're going to cover how to use different third-party libraries in your android app we'll talk about method decomposition and reuse and we'll look at how do you make api calls using a library called retrofit covid19 has dramatically changed what any of us thought 2020 would look like and all the data indicates that coronavirus will continue to impact our society in a very meaningful way for a lot of 2021 as well as engineers or app developers the best thing we can do is look at the data for covid19 and understand it and display it to other people so we can all become more educated about this virus unfortunately google play decided to prohibit all kovid 19 related apps unless they're from a government or medical institution so i decided to build my own covid19 tracking app and i'm going to show you how to build it as well our app uses the same ui components as the robinhood stock trading app and the whole app is going to be written in less than 200 lines of kotlin code let me do a demo of the app the purpose of what we're building is to be able to quickly see trends around the growth of current virus both at the national level and state level by default when we open up the app we're displaying the number of positive covid 19 cases nationwide or across the whole us and i have the ability up here to toggle between the number of negative cases per day number of positive cases or number of deaths per day and you'll notice that notice that the graph animates in down here we have the ability to toggle between the different time scales so maximum means display all the data we get back from the api which is generally starting from around march one month means the most recent one month of data in one week means most of the most recent week of data by default we're showing maximum the other option i have is to actually scrub on the chart on this line chart and you'll notice that we update the metric the individual metric number shown down here it animates in and it displays the exact quantity of this metric on that day so on april 25th 2020 though there were roughly 1800 deaths in the u.s i also have the ability to dive into a particular state so for example in california you can see that there's been a recent increasing trend in number of positive cases per day in california and the same things apply i could also dive into the number of negative cases in california or number of deaths and if i wanted to look at a particular day i can scrub over the graph and you can see how the text animates in down here if you keep watching you'll learn how to build exactly this step-by-step the data for our app is coming from the covid tracking project which is the most reliable data source i could find for getting daily updates on the number of chronovirus cases two of the core components in our application this chart which is called a spark chart along with this changing text view called a ticker view both of them are coming from open source projects from the robinhood app both the robinhood app and our app are displaying the change of a metric over time stocks versus chronovirus cases so there's a natural fit to using the same components that they're using in the robinhood app and robinhood is considered one of the best design android apps out there so there's a lot to learn from what they're doing i hope you're as excited as i am to start building this project in the next video we're going to fetch data using retrofit from the covid tracking project api our goal in this video is to talk to the covid tracking project api in order to retrieve the data that we need for our application the way we'll go about doing this is by using the api created by the kobe tracking project our phone or our application is the client and we're going to be making a request to the covet tracking project and getting a response which contains the data we're going to be making a get request on this particular url api v1 slash us daily.json and what that represents is we want to retrieve the daily data of the number of chronovirus cases nationwide and the covid tracking project will respond with json data and that json data will contain the metrics for each day up until the most recent day in addition to getting the data nationally we'd also like to be able to get the per state data for coronavirus and in order to do that there's one more endpoint in the api that we'll need to hit and that will give us back a list of the data per day per state now we have an idea of what we're trying to do we can start the implementation we're going to use a library called retrofit on android which makes working with apis really straightforward what i have here is a totally empty android project so if i run it now you'll see the emulator showing the hello world application the first thing i'm going to do is go into the android manifest file and because we're talking to an api over the internet we need the internet permission in our application let's start typing users permission internet the next step is to include retrofit in our project so what i have open here is the official site for retrofit which is a library developed by square and i'm going to go to the download section so we can figure out how can we include this library into our project so here you can see it says for gradle which is what we're using you need to include this line i'm going to copy this and notice that it says insert latest version here so we're going to fill that in later but i'm going to go into our project and go into build.gradle and make sure you're going into the build.gradle which is located in the app module and then in the dependencies section i'm going to add one more dependency which is for retrofit in order to get the latest version i'm going to open up github and tap on releases and you can see that the most recent release is 2.9.0 so let's replace this with 2.9.0 one more thing that you'll need in order to use retrofit is a converter if i tap on the section around retrofit configuration the converters are used by retrofit to translate the api response into a model that we can work with in our application and i'll talk more about what that means later on we're going to use json for this so i'll copy the dependency for json go back into android studio and paste that in with the same version number as what we used for retrofit finally the last thing we'll need to do before we can build our project is instruct gradle to use java 1.8 and the reason for this is because more recent versions of retrofit use a component which uses a java 8 feature which are lambdas so in order to enable java 8 we go up into the android section of the build.gradle file hit enter a few times and we're going to add a section here called compile options in this section we're going to have two lines one for source compatibility and the other for target compatibility and for both of these the value was going to be java version version 1.8 at this point it's worth making sure that we haven't screwed up yet so i'm going to tap sync now and we see a sync success the next thing is let's build our project and we don't expect any ui or functional changes but we should still be able to build the project and see hello world in order to use retrofit the first thing i like to do is define a new file which is an interface that retrofit will consume in order to talk to our api the way that works is we want to create a new interface file in the same directory where main activity is located let's define a new file here a new kotlin file and call this covid service the idea of this kovic service interface is that we're going to have one function defined here for each endpoint in the apf so like we talked about earlier there are two endpoints that we're interested in one which is for getting the national data per day and i'll call that get national data and the other is for getting the per state data and i'll call that getstate's data plural because we're getting the data across multiple states the way retrofit works is that we need to add in a corresponding annotation for each method defined in our interface so for example we're doing a get request on the endpoint us daily.json for getting all the national data next we'll add a return value for each method that we've defined retrofit and json will automatically take the json data returned from the api and turn that into data models that we can use in our application this is going to be enclosed in something called a call object that retrofit gives to us and then our job is to define the data class that we'll actually be using in our application and i'll call that covet data so we're going to have the return value be a call which is a list of covet data because there will be one element in the data we get back for each day the return value for the other function in our interface is going to be the same a list of covadata and i'll show that to you later and the annotation is going to be similar again except for the endpoint is states daily.json instead of us one thing that's worth noting about this api which is really nice is that there's no authentication or api key that you need in order to use it so now let's define this data class covet data i'm going to again open up the project tool window and let's define a new kotlin file which defines covet data cova data class is going to be a data class which represents the data that we care about from the json object in the api we're going to use a annotation called serialize name which defines the mapping of the json key to the variable that we want to map it to in our data class so for example there's a key in the json object called date checked and we're going to map that to a string which is also called date checked and i'm going to show you that in the actual json result that we get from the api so what i have here is the documentation for the covid tracking project api and if you scroll down you can actually see the different endpoints available in this api the data that we're getting back right now is historic us value and we can issue the get request in the browser in order to dive into the json data and you can see the data that we're getting back is enclosed in this json array that's what these square brackets mean and inside of this json array are different json objects this represents one day worth of covet 19 metrics for the us the covad data class we've defined in our project represents one json object here and the attribute that we've already parsed out is this one called date checked so we're actually parsing out this string we're going to ignore a lot of the attributes in the json object but because we're interested in the change per day the attributes we are going to parse out are negative increase positive increase and depth increase in addition when we are querying for state data we're also going to care about an attribute called state so i'm going to include one attribute in copa data for each of the json keys that we just talked about positive increase negative increase and depth increase in addition we're also going to have one more key for the us state that this data represents one optimization we can do is if the serialized name exactly matches with the name of the variable we can get rid of the serialized name annotation and that's the case for each attribute that we've defined i'm going to go ahead and delete the serializer name for all of them one thing we should fix here is that the positive increase negative increase in death increase won't be of type string but they'll actually be of type integer because they represent the number of new cases found in each of these categories so now we've defined the cova data class we can go back into covert service and we can see that the red underlines have gone away now we can put all the pieces together in main activity the oncreate function will get called by the android system when our application boots up when our activity is being created at that point we want to make the api request to fetch the national data so we can display a chart on the screen showing it we'd also like to get the state data because as soon as we get the state data back we can populate our drop down or spinner so the user is able to drill down into a particular state here's where we're going to use retrofit the first thing we'll do is create an instance of json using the json builder because we're going to need that to create an instance of retrofit we use the retrofit builder passed in a base url which i'm going to do shortly and add in a converter factory where we pass in the json converter factory and pass in the json object and then we can call dot build we can now use the coded service class that we created in order to create an instance of the copied service and on this we can call the methods that we had defined and i'll get to that in a little bit but first let's go back and define the base url as a constant up here so in cobit service we defined the end of the url which is us daily.json and if we go back to the browser you can see that that basically captured this last portion of the url the base url will be everything except for that which will be this portion in the beginning so i can capture that put it here and let's add this in in our retrofit builder let's go back and uncomment this covet service like a national data and i mentioned how in kobit service the return value is not the model data directly but something which is graphed inside of a retrofit call object and the reason for this is because of the asynchronous nature of doing anything with network calls so we get back this call object because that is how we get notified of the success or failure of our api request so on the call object that we get back we'll enqueue a callback and this callback will be parameterized by list of cova data we're going to copy that in we can now override the methods that are required as part of the callback so if i tap on the red light bulb we can have android studio help us implement these members there are two methods on failure and unresponsible override both them and in on failure all we want to do is log an error something went wrong with api call so we're going to put a log.e which means log at error level put the tag and then indicate on failure and also include the throwable t which is included so let's define the tag at the top of the file and my convention for that is always to have the tag name be the class name for the on response method the first thing we'll do is simply log at info level that we entered into the onresponse method and we'll also include the actual response that we get back next the body of the response will contain the list of copa data that we should have been able to parse from the api if this data which represents the national data is null that means we got an invalid response from the server and we should log something at warning level the log.w and just indicate that something went wrong once we've gotten past this if statement we know at this point that our data is valid what we'll do here is save the national data into a member variable which is accessible throughout the whole main activity class so i'm going to define national daily data and define that as a property on main activity and this is going to create for us a late init var national daily data which is a list of coveted data one important point here is that the data we get back from the api starts with the most recent data however for graphing purposes we'd like to start our data with the oldest data first and so we're going to call nationaldata.reverse in order to get the proper ordering for now the only other thing i'll do in this method is add a log statement which indicates that we're going to figure out in a subsequent video how to take this national daily data and display it in a line chart to finish off this video i want to also fetch the state data and then validate that this is actually working what we've done so far is used retrofit to talk to the api and automatically convert the json data we get back into a class we defined called covadata which includes attributes such as a date of when this data is relevant number of positive cases negative cases debts and when we talk to the state endpoint we also want to know the state that this data is relevant for so i'm going to represent this in this light orange blob which has covered data inside of it and it contains a particular date what we just did for the national daily data is we reversed the order of the list that we got back from the api so the oldest covet data is at the front of the list and the most recent is at the end of the list so a similar logic applies for the state data but there is a wrinkle because all the state data is combined in one large list we'll get all the data for all states for may 1st then may 2nd and then and so on and so forth however in terms of being able to graph the data all really care about for example is being able to retrieve all of the data relevant for alaska and so what our job is is to take this big list of data and pull out all the data relevant to alaska and put that into a separate list so the idea is that we're going to take this big list and break it down into a map and that map will have a key of the state and the value will be all the coveted data relevant to that state so with that understanding now we can define the state data so i'm going to do something quite similar so i'll say coverage service dot get states data and cue it and this is actually going to be quite similar so i'm going to initially just copy all this and we're going to leave the log messages here but instead of calling the return value of response.body as national data this should be called states data similar to what we had before we first want to reverse the whole list we get back but then we want to group this large list down on a per state basis we're going to call this nice group by method in kotlin and pass in the argument that we want to group by and that'll be the state attribute of every covat data object so this is actually going to return to us a map rather than a list so i'm going to call this per state daily data and i'm going to create a property inside of main activity so again this property can be accessed throughout the whole class which we're going to use in subsequent videos this is a map between a string which is a state and a list of copa data which is the chronologically increasing cover data over time once we've computed this per state daily data the next thing is we'll want to update that drop down or that spinner with the state data so that will happen in a later video before we try this out the last thing i like to do is make one small improvement if you go back to kova data you'll notice that this attribute date checked is a string however in order to do computation and make it easier to display this date in different ways we would actually like to have this date check to be of type date java util date rather than a string and so in order to make that happen i can define it as a date here but we need to pass in another method in the json builder so json will know how to convert the date string and turn it into a java date object that can be done by calling this method set date format and you pass in a pattern the pattern that the api we're working with complies with is the following so with that we should be able to properly parse out dates all right so now we can finally try this out what i want to do to validate that we have something working is go into the unresponse method and where we have a log statement once we've computed the national daily data let's put a break point right there and now instead of running the app like normal hit this button for debug app so as soon as our program installs and we get into this onresponse method our program should halt execution at this point and so you can see that that happened here we can take a look at what is the value of this variable national daily data that we just computed so you can see that the size of this list is 134 which is sensible because that means that we have 134 days worth of data and if i expand this we should ideally see all this sorted chronologically so the oldest day is january 22nd january 23rd so it is ordered which is great and it goes all the way up until the most recent day so this gives us confidence that we are able to parse all the data properly and you can also see the other values like positive increase negative increase death increase those are also being parsed out properly here now that we have the data which will power our whole application in the next video we are going to build out the ui which will display the chart and the metrics our goal in this video is to update activitymain.xml which defines the ui for our application and update it to include the different components that we'll need for our coronavirus tracker once we've done that in the next video we'll be able to wire things together and actually have the data that we parsed out in the last video together with the ui component that we had in this video and be able to show something on the screen taking a look at the final ui of our application there are a couple different ui components on the screen at the top you have the label for this drop down and they also have a drop down which is called a spinner on android for the purpose of this video i'm going to ignore that spinner and just have the state text view shown there below that we have something called a radio button group and the radio button group contains three different radio buttons and the idea of a radio button is that it acts somewhat like a normal button except for you can only have one out of those three buttons in that group selected which makes sense because we only want to be able to graph one of these metrics in our line chart below below that we have a line chart and in particular this is called a spark chart and we'll talk about how to integrate the robin hood library to include this below that we have one more radio group which has three radio buttons and then finally at the very bottom you have two text views one which is for the date of what metric is being shown then to the right of that we have the metric corresponding to that date here's the default activity main that comes in with any empty project the first thing i'm going to do is delete the default hello world text view and instead bring over one more text view and for now i'm just going to go into the design tab we're going to toggle between the design tab and code tab quite frequently and just to give myself more room i'm going to open up the design tab and make that the only thing shown on the screen so we have this textview on the ui i'm going to call this tv and id of tv select state gives us a text of state and then have it be 16 dp to the from the top and left let's also make the text larger the text appearance large next i'd like to bring onto the screen a radio button group so i'm going to go into the button section and bring over a radio group and then have the width of this radio button group be match parent the whole width let's zoom in a little bit have this be constrained to the bottom of the state text view and then inside this radio group we want three radio buttons so i'm going to take the radio button and drag it inside of the radio group in the component tree the first video button will be radio button negative this will have a text of negative and also let's make the layout with wrap content rather than match parent so it shrinks let's copy over this radio button two more times so we'll have one more for radio button positive the text will be positive and then one more for radio button death in order to have these radio buttons be horizontal rather than vertical we need to set the orientation attribute of the radial group and it looks like the width here should also be wrapped content same as this and then also we want to center the contents of the radio group inside of it so i'm going to select the radio group one more time and set the gravity attribute and have the gravity be center and then apply so now you can see that it is in the center both horizontally and vertically below this radio group we'd like to have a line chart which shows the data on a per day basis so to do that we're going to use a library from robinhood an open source library called spark and this is a library to show a simple android sparkline chart view so if you scroll down to the very bottom then we can copy over this line that we're going to add into our gradle build file i'm going to open up the build.gradle file it's located in the app module add that in and then tap on sync now while that's syncing let's go back to github and we can see how to use this there's a section here about usage all we need to do to include this spark chart in our application is add the spark view to the layout then going back into android studio we can open up the activity main.xml file and to add the sparkvue i want to go into the code tab so if we can just start typing sparkvue here and then android studio will help us with autocomplete the width will be matched parent because we wanted to take up the whole width of the screen and the height for now it's going to hard code in 150 dp and we'll change that later one thing we need to do also is we're going to position the sparkvue vertically below the radio group above it so i added this id on the radio group called radio group metric selection so now we can say the top constraint is to the bottom of the radio group metric selection we'll also give the sparkvue an id of sparkvue so let's see what this looks like in the design tab so you can see that we have a space allocated for the spark view below the spark view we have one more radio group and this is going to be vertically positioned below the spark view we'll give this radio group an id of radio group time selection because it'll be used to select the time range of the spark chart we'll add a 16 dp top margin on the radio group and then we're going to do something very similar to what we had before we add in 3d radio buttons update the text and id and position them so that the radio group is horizontal the three time scales that we're going to allow the user to pick from are the most recent one week most recent one month and the maximum amount of data that we get returned from the covet tracking project api as of today the max will typically be a period of around four or five months because we start getting data back from the api around january or february the last thing we need to do to complete our basic layout is add the two text views at the bottom of the screen and these will be relative to the bottom of the parent or the screen and not relative to the elements above it so we'll drag out a text view have this be 16 dp from the left end of the screen and concentrate to the bottom and let's also give this a height a hard-coded height of 80 dp this will be a text view for the date the date label and let's change the text appearance a little bit to make it body one let's have one more text view which is also 80 dp tall the same exact height and this text view is going to contain the metric value we'll say tv metric label this is going to be relative to the right end of the tv date label and it'll be to the bottom of the parent the gravity for both of these text views is going to be center and this text view is going to extend the whole remaining width of the screen which is not taken up by the first text view let's provide some sample data for each text view for example this metric it might let's get rid of the text attribute and let's use the tools namespace here which is this wrench text and let's put in a sample data point of 4354 just to see how it might look let's make this text bigger we'll say display one as a text appearance so it becomes a lot bigger and then for this text view over here let's also put in a sample date may 30th 2020. our goal now is to have the sparkvue take up all of the height remaining in the screen once all the other widgets are placed so the way we'll do this is actually allocate the widgets above the sparkvue and below the sparkvue and have them be glued to the top or bottom of the screen so rather than having this radio group be relative to the bottom of the sparkvue i'm instead going to delete that constraint the top constraint and have that instead be to the top of the bottom components that we have like that now i'm going to set the bottom of the sparkvue to be the top of this radio group and instead of hardcoding the height to be 150 now we can just say match constraint and that should now fill up the sparkvue to be all the remaining height so now we have completed the basic layout for our covet tracker in the next video we're going to go back into main activity and fill out this to do so we're going to get rid of this to do and actually reference the sparkvue that we put on the layout and populate it with the national daily data that we parsed out from the previous video i'll leave a link in the description to the code we wrote in this video so you can take a look at the raw xml if you want where we left off in the last video is we created the basic layout for our covid tracker application our goal in this video is to populate this graph to update the sparkvue with the data we get back with the national per day data of chronovirus cases in the code what that means is we want to get rid of this to do item and replace it with the actual code to render the spark chart i'm going to delegate the work of updating the spark chart with our national daily data into a separate method called update display with data this will take in as a parameter the national daily data and then i'll have android studio help me to create this method so i'll hit that red light bulb and then create the function inside of main activity instead of calling this parameter national daily data i'm going to call it daily data because we're also going to reuse this method for the per state data this is a list of covada which is a data class that we had defined earlier there are three things that we want to do inside of this method first in order to render data inside of the spark chart we need to create a spark adapter next we want to update the radio buttons so by default the positive cases and maximum time range is selected and third we want to display the metric for the most recent day of data that we have let's start backwards so the first thing we'll do is display at the bottom of the screen the metric for the most recent date again i'm going to delegate the work of this into another function i'll call this update info for date and what we're going to pass in here is a particular day of data and the data that we want to pass in here is the most recent date and because our data is ordered chronologically we can pass in daily data and pass in the last element i'll i'll have android studio help us again to create this method and we're going to call this covet data the parameter so the objective of this function is to update the two text views at the bottom of the screen with the data inside of this parameter so first is the metric we call this tv metric label that's referring to the text view at the bottom right of the screen and the text attribute of this textview is going to be the number of coronavirus cases either positive negative or number of deaths on that particular day for now because we're hard coding in positive let's go with that that'll be covered data dot positive increase and we actually want to format this number with comma so it's more human readable rather than just showing the raw text in order to do that we're going to use a convenient class called number format so we'll call number format.instance.format and the format method on number format takes in a number and it will automatically format it to include the commas and decimals so our covadata has a date checked attribute which is a javadate object we want to take that javaday object and turn it into a nice string which looks something like may 30 20. so the way we'll do that is with something called simple date format and the first parameter here is the pattern of the date so what we care about is the month which will be capital ms so three of those letters so for example if it's marked it would be mar then we have the particular day in the month followed by the year and that's denoted by the lowercase y the next parameter is the we had to pass in a locale we'll put in locale us and we're going to save this in a variable called output date format that we have this output date format we can use that to format the javadate object inside of our covadata and this is going to be a string which we will put into the text attribute of our text view and we called it tv date label let's continue working backwards the next step is to update the radio buttons to select the positive cases and max time radio buttons by default this is actually very straightforward because all we need to do is specify the particular radio buttons which should be checked that's the attribute name to indicate that it should be selected so i'll say radio button positive and that is checked attribute should be true and then similarly for radio button max let's run the app now and see how it looks so you can see as soon as the network requests to fetch the national daily data came back then we execute the logic inside of the update display with data method and that is what is updating the bottom text views with the particular date along with the metric and also these radio buttons finally the last thing we'll do is create a new spark adapter which will instruct the sparkvue in our layout how to render the data contained inside of this list of coveted data so i'm going to pretend like we already have the spark adapter class i'm going to call it covid spark adapter and we're going to construct a new instance of this coveted spark adapter and this will take in the constructor the list of daily data that we have we'll save this into a local variable called adapter and now i'll tap on this red light bulb and have industry to help us to create this class we'll extract it to a separate file in the same package which is fine we can leave the parameter name as daily data and we can see that this file did indeed get generated inside of the same directory same package where main activity is located so we have this kovid spark adapter this coveted spark adapter has to be a subclass or has to inherit from the spark adapter class which came in from the open source library so we're going to put a colon here and say spark adapter and we'll need to import this and you can see that it does come in from the robinhood library and now there's a red underline under the declaration the class kovid spark adapter if we tap on the red light bulb we can see how to fix the problem which is by implementing these three members spark adapter is an abstract class so we need to provide an implementation for these three methods and if we tap on ok android studio helps us by automatically defining these three methods with the proper parameter and return type because we passed in the daily data in the constructor it's straightforward to implement each of these three methods so i'm going to first change the daily data to be a private member variable so i'm going to call it a private val the easiest method is get count because this is simply going to be the size of the list so because it's a one line statement we can use this nice feature in kotlin to get rid of the method body and just say getcount is equal to dailydata.size the idea of getitem is that given an index which is a position in the list of data we would like to return any which means a generic object which represents the data object at that position so again this is actually one line you can just index into the list of daily data so i'm going to get rid of the body of the function and say get item at that particular index is equal to daily data at index finally is get y and the idea here is that given a particular position in the graph we want to retrieve the corresponding value at that position right now we're only going to be graphing the number of positive cases per day so given an index you can grab the corresponding cova data at that position i'm going to put that into a local variable called chosen day data and then our job is simply to return the positive increase that attribute on that covet data the return type of get y is a float but this attribute is of type int and so to create turn it into a float we just call the two float method so we defined the basic working version of the spark adapter we can go back into main activity the error goes away and now we have one more line to write which is we have to grab a reference to the sparkvue and set the adapter property to be the adapter that we just defined that's it let's try it out when the app boots up you can see that we are graphing now in this spark chart the number of positive coronavirus cases nationwide over the maximum time range and at the bottom of our application we're showing the particular data the particular metric for the most recent day now that we have the ability to show one chart on the screen we're going to extend this functionality so that we're able to respond to changes in radio button click in this video our goal is to make this spark line chart more interactive so that we update it when the user taps on any one of these radio buttons for either selecting a different metric to show or selecting a different time scale the way we'll go about doing this is to map the radio button selection to an enum which represents the metric or the time scale i want to create a new class called chart options and this chart options kt file will encapsulate all the knowledge about the different ways we could render this chart this spark chart and there's going to be two enums inside of this chart options class the first will be for the metric being shown and there are three possible metrics that we can show on the graph one is negative negative cases of coronavirus one is positive cases of coronavirus and then lastly is the number of deaths the other enum we'll define here is the bottom row of radio buttons which are the time period over which the chart should display data we're going to call this enum class time scale and this enum is going to have an associated integer which represents how many days does time scale represent i'm going to call this val num date and this is going to be an integer so there are three possible options in the bottom row of radio buttons one is for one week of data and the corresponding enum is seven days for that then we have one month and we're gonna assume that one month is always 30 days and then finally is maximum which means show the max amount of data possible we don't know ahead of time the number of days associated with the maximum time so we're going to instead put a special value which is going to be negative 1. the combination of these two enums metric and time scale cover all the possible ways that our chart our spark chart could be rendering data there's also a notion of our chart having a certain state our chart has to be displaying one of these metrics and it has to be displaying data over exactly one of these three time scales that state will live inside of the adapter for our chart so inside of the adapter class i'm going to define two variables here one for the metric and this is going to be by default showing the positive cases and notice that this is a var not a valve because we do expect that this metric will change over time as the user taps on one of those radio buttons in the top group and there's one more variable which is the number of days ago and this is by default going to be the maximum time scale now that we've defined these two variables our adapter is now aware of what it should be rendering in the spark chart so in the function get y which returns a float of the corresponding metric value at this position at index instead of always returning the positive cases of chronovirus we should instead check the value of the metric variable i'm going to use the when construct in kotlin and we'll return a different value depending on the metric we'll say return when and depending on the metric we'll do something different when the metric is negative then we want to return the negative increase dot to float when the metric is positive we want to do something quite similar except this should be positive increase and then when the metric is death we want to report the number of deaths on that particular day and then later on we're going to use days ago in another function that we override on the adapter there's one more place back in main activity where we hard coded in the assumption of always returning the positive number of chronovirus cases so here as well in this update info for date method we want to again check the metric enum in our adapter and then return the corresponding metric so in order to have access to the adapter inside of this method instead of defining it locally here i would like to make it a property so i'm going to delete the val and now inroadstudio will show me this red light bulb and i can use android studio to create the property for me so now we have this adapter and right here we want to do something quite similar so val num cases should be again something which is based on the adapter dot the metric and if the metric is negative then we want to return the cova data which is a parameter passed in here we want to display the negative increase attribute of this cova data class and then in the case of positive you want to show positive increase and then finally in the case of death we want to show the number of increases in the number of dots so instead of always placing this value in we can instead show num cases we haven't made any functional differences in the app yet because we haven't added any event listeners for when the radio buttons are changed so all that logic for listening to changes in any of the ui elements we're going to put all that in a function called set up event listeners i'll call that method right here set up event listener and we'll define this method inside of mainactivity the reason i'm calling this method here is because we only want to make the ui interactive when there is actually data to show so as soon as we get the success from our api call to get the national data that's when we want to hook up the radio buttons and the ability to actually scrub on the graph before that it doesn't make sense so in setup event listeners there's two things we want to do first is we want to add a listener for the user scrubbing on the chart and second we'd like to respond to radio button selected events i'll leave what to do for the second item because we'll get to that later in order to allow the user to scrub on the chart which basically means hold down on the chart and drag their finger over it the first thing we need to do is set the is scrub enabled attribute to be true and then we need to set a scrub listener on the sparkvue and as you can see here the parameter that we are provided in this set scrub listener is a value which is a value corresponding to one data object in the chart in particular if you go back to the adapter you can see that the item data that we get back is going to be the return value of this function get item and we're turning back the covet data element at that position so going back into my activity i'm going to call the parameter here item data and then the job here is in the body of this function which will be invoked for us we want to update the ui with this information as a sanity check one thing we can do is just check if the item data is indeed cova data which it should be because that's the only thing we're returning but this is kind of a safety check then we can call the method we already defined update info for date with this item data so we're going to be updating that bottom ui component to show the date and the metric at that date let's run this so now if i hold down on the chart and i move along you can see that i am able to have this vertical line show up and as i move it along you can see the values at the bottom get updated so on april 18th i'm able to see exactly the number of positive chronovirus cases nationwide and this makes our application a lot more useful because we're giving the user an ability to drill down into specific days the last thing we'll do before hooking up the event listener for radio button taps is go back into the kovid spark adapter and make use of this days ago property the idea of days ago is that we want to change the time scale of our graph to only show that amount of data the way we'll do this is by overriding one more method in the spark adapter class it's called get data bounce super.getdatabounds this invocation of the parent method which already defines this is going to return to us a rect f or a rectangle composed of float coordinates so i'm going to capture that supervalue into a local variable called bounds and the idea here is that this rectangle defined by bounds will dictate what exactly is shown in our spark chart if you wanted to shorten or expand the amount of data shown in the chart all we need to do is update the left end of this bounds rectangle so we can say bounds dot left is equal to instead of the whole data which is count from basically invoking this function getcount instead of showing the whole amount we'll say count minus seven which means top off everything except the last seven days worth of data the most recent seven days worth of data and this needs to be afloat so we would have to call to float here then we can return these modified bounds of course we don't always want to subtract seven from the count and only show the last seven elements of the list instead we'd like to change it based on this days ago property instead of having seven here we want to get the days ago variable get the corresponding num days property out of that enum and turn that into a float this will work in the case of looking at the last one week or one month of data because the corresponding value of num days will be 7 or 30. however when the max option is selected instead of reducing the amount of data shown by subtracting from count we would instead like to show all the data so that's a special case where we'll say if days ago is not equal to time scale dot max only then do we want to reduce the amount of data shown so if days ago is max scale bounds will actually be unchanged which is what we want now we're finished laying the groundwork for being able to respond to when the user taps on the radio buttons we simply need to modify the metric or days ago enum inside of the adapter now we can go back into mainactivity and write the logic to respond to radio button selected events so let me remove the to do because we're actually going to complete this item right now there are two radio button groups that we're going to respond to the first is the set of radio buttons on the bottom of the screen which is for selecting the time so radio group time selection we're going to set a unchecked change listener so this is going to invoke the body of this function whenever one of the radio buttons in that bottom group has been selected this method that's going to get invoked has two parameters one which is group which we don't care about so i'm going to change that name to be a underscore followed by a checked id and the checked id is the id of the radio button that was selected so the only thing that really needs to happen here is we need to update the days ago property in our spark adapter to be the corresponding value when one of the radio buttons is tapped on so for example if i tapped on the radio button for one week i should set adapter.days ago to be timescale dot week so rather than hard coding it of course we should do this contingent upon the value of checked id so we'll use the when construct i'll say when checked id and if the checked id is r dot id dot radio button week and we'll map that to timescale.week if it's r dot id dot radio button month then we'll set the time scale to be month and then otherwise the time scale is max once we've updated the days ago the only other thing we need to do is notify the adapter that the data the underlying data has changed so the adapter knows to re-render itself the other radio button group is at the top of the screen for displaying a metric so we'll do something quite similar radio groupmetricselection.set on check change listener you don't care about the group but we do care about the checked id so i'm going to do another blend based on the tucked id if the radio button is positive then we want to update the display metric to be positive so i'm going to actually delegate the work of updating the display metric into a method called update display metric and i'll pass in positive here let's also do the same thing for the radio button negative and then finally for death radio button death let's define this method now the only thing that needs to happen here is something quite similar we're going to update the metric variable in the adapter to be the selected metric and then we'll notify the adapter that the dataset has changed let's try it so by default we're seeing the nationwide number of positive coronavirus cases over the maximum time scale if i change the metric to be negative you can see that we are seeing a different chart and similarly with the number of dates i can also do the same thing for showing only a certain period of data so one month you can see that i'm only seeing that last segment and then week i only have seven data points being shown here so that looks like it's working in the next video we'll make a few improvements to the ui when the radio button is selected and we'll add in a spinner or a drop down component at the top of the screen which will allow the user to look at the data for a particular state there are two things i'd like to do in this video one is i'd like to make some improvements of what happens when i change either the metric shown for the spark chart or the time scale shown and second i'd like to include a drop down or a spinner component at the top of the screen which will show all the states and if the user selects a particular state we should update the data shown in the chart for all the covid 19 cases of that state so first one thing you'll notice is that when i change the metric being shown on the graph this bottom component this text view doesn't get updated so we're actually showing wrong information here right this 20 000 is for the number of positive cases of chronovirus on this particular day and not the number of deaths so this should really be updated when this metric gets updated the way we'll fix this is by adding some logic in this method update display metric this method is invoked every time the user changes the metric shown on the graph so what the logic we have here is doing is updating the metric on the adapter we'd also like to reset the number and the date shown in the bottom text views so really what we'd like to do is call the method that we wrote a while ago called update info for date so the idea here is that we want to pass in the last covet data object and have this bottom component show the most recent data the last day of data that we have along with the metric corresponding to the metric passed in here and that logic is already built inside of the update info for data class so you can see that we're already checking the met adapter metric so we're going to show the right value the question now is how do we know what to pass in here the issue is that we need to know what data is currently being displayed in the sparkvue if the data being shown as a national data then we can take the last element of that list of cova data representing the national chronovirus data and pass that into update info for date for date but if we're showing a particular state's data we need to know what state we're showing and grab the last day's worth of data for that state and pass that in so we need to have some way of knowing what is being shown currently to do that we're going to add one more property or member variable inside of main activity i'm going to define a property called currently shown data and this will hold on to the data that's currently being displayed inside of the sparkvue and the reason i'm assigning the value here is because this method update display with data takes in the list of data which is being shown in the sparkvue so we know that this method has to be called at the beginning and every time that the data for the sparkvue has changed currently shown data is going to be equal to exactly the parameter passed into update display data now android studio can help us to define this property create property currently shown data and now we can go back to update info for date and then pass in the last element of the currently shown data one more thing i'd like to do before we try this out is a quick design improvement based on the metric being shown we can display a different color for the chart so i'm going to add a comment here which says update the color of the chart and what we want is there's an attribute on the sparkvue called line color and we want to set this to be equal to some color integer the way you get a color integer is you can say context compat dot get color and you can pass in context which is this and a color resource so there is a predefined colored resources like r dot color dot let's say color accent this will give us back a color inch and i'm going to actually add an annotation here to make it obvious that this variable is of type coloring so we can pass and color into here and then also we can update the text view which represents the metric so we call that tv metric label and we're going to set the text color color inch so now based on the metric we want to show a different color here rather than just the color accent here are the colors that i picked out which i thought were intuitive for each of the metric types negative cases is green positive cases is this orange color and number of depths is this red color so back in android studio i'm going to paste in those hexadecimal values inside of the color resource file so instead of resources values you should already have a colors of xml and we're going to add three more colors here one will be color negative and then this will have a value of the green color then we'll have color positive this has the orange value and finally we'll have one more color representing the death metric this has that red value now now that we've defined these three colors we can go back here and again use the when construct the when statement in kotlin we're going to define a color resource which is the result of this when statement instead of the went statement for each metric we'll map it to the color resource that we had so for example metric negative will map to r.color.color negative positive will be color positive and death will be color depth now we can use the colored res value when we're obtaining the color int using contextcompat.getcolor and finally last thing we can do before we run this is inside of this method update display with data we're calling update info for date we're already calling this method inside of update display metric and we're actually doing other useful things such as updating the line color so rather than calling update info for date i'm instead going to call update display metric and pass in metric positive because that's that's always going to be the default metric shown let's try it so now you can see when we run the app initially we are again seeing the positive cases of coronavirus over the maximum time scale but we have this nice color applied to it this orange color if i change this to be death we can see it gets updated to red and importantly the texture at the bottom showing the exact metric for the most recent day has been updated to reflect the chosen metric the last major piece of functionality for our app is allowing the user to select which state they want to see data for so back in mainactivity this is corresponding to this to do item that we had left in one of the prior videos so we're finally going to do this i'm going to remove the to do and i'm going to delegate the work of updating the spinner with the state names into a method called update spinner with state data and this function is going to take in one parameter which is the list of all the states to show and that will simply be the key set of this map so if you recall the per state daily data is a map of each key being a state and the value being all of the coveted data for every day of that state so now we can have android studio help us to define this method i'll define it in main activity and i'll have the parameter be called state names and this is of type set of string the objective here is given these state names which are a set we want to turn that into an ordered list and we're going to take that ordered list and pass that in as the input to our dropdown component the first let's turn our set into an ordered list where we're alphabetizing all of the states so we'll call state names dot to mutable list so we can actually change and mutate the contents of this list we'll call this variable state abbreviation list and it will contain the abbreviations for all 50 states plus several u.s territories and we want to alphabetize this list so we want states like alaska or alabama to show up at the top and states like wyoming to show very at the very end of this drop down so we'll call dot sort and then we also want to have one special entry in the state abbreviation list which is to represent the national data right we're not going to get that in the set of strings passed in here because this only contains state names so we're going to have to add it manually right here and this is going to be the very first element in our list so i'll add this at position 0 and i'm going to have a special entry which is called all states which basically means i want to see the national data so again android 3 will help us to define this variable all states and this is going to have a value a hard coded value of all nationwide and i'm actually going to define this outside because i can make this a const so what we want to do next is take this ordered state abbreviation list data and add that as the data source to our spinner next we need to add the spinner into our ui so going into activitymain.xml we would like to be able to add a spinner component at the very top of this layout that we're building i'm not a big fan of the built-in android component for this which is this spinner component i think it's really hard to use and it doesn't look that good instead we're going to use a library called nice spinner and this is easier to work with and in my opinion it looks better so let's go down first to how to include this library into our project so inside of the build.gradle file we need to add a dependence like normal but also we should add this section about repositories so i'm going to go into android studio go into the build.gradle file which is located inside of the app module and you probably won't have a repository section here so right after we added compile options let's add repositories and we want to add this maven repository i'm going to copy this line and paste that in and now we should be able to add the dependency and copy this line and paste it in here tap on sync now and hopefully we're able to download this library properly looks like it succeeded so now we can go back into activity main and we can include it in this area that we allocated for it to do this i'm going to go back into the code view of our layout and right here is the label which describes what this spinner is for i'm going to create another component which is called spinner and it should be nice spinner we'll set the layout width to be zero dp because we want this knife spinner to take up as much room as possible the height can be wrap content and we're also going to add a margin start and end there's a few other properties we can add in here ellipse size we're going to ellipses in the end and the maximum number of lines will be one and then the text appearance of what we're showing should be large and now our job is we need to constrain this view appropriately for the horizontal constraint you want the left end of the spinner to be up against the right end of the select state text view so i'm going to say constraint start is to the end of the tv select state and then the end constraint is going to be to the end of the parent because we wanted to go to the end of the screen for the vertical constraint we're going to have the top and bottom of the spinner be equivalent to the top and bottom of the select state text view which is to the left so bottom bottom of and then we want to pass in cv select state and then something quite similar for the top and one last attribute that i forgot to add is something called pop-up text alignment and i'm going to put start here just so that in the drop-down all of the states are left aligned or start aligned so if i go into the design tab now we should see that there is a space allocated for the spinner one thing we can do here is just give this an id because we'll need to refer to it in our main activity.kotlin file we'll call it spinner select now we can go back into main activity and let's reference this spinner that we just added so i'll say spinner select dot attach data source and we'll pass in the state abbreviation list the last thing we need to do to hook it all up is we'd like to be notified when the user has selected another state from the drop down so on the spinner select widget we're going to add a set on spinner item selected listener and this takes in four parameters the only ones that we care about are the parent and the positions i'm gonna put an underscore in for the other params and this will now this method will be invoked every time a new item in this drop down is selected so in order to get the selected state we're going to say parent dot get item at position it'll pass in position and we know that this is going to be of type string our data source for the spinner is a list of string i'm going to cast this as a string and save this as the selected state now we'd like to get the corresponding daily list of cova data for that state so i'll say per state daily data and then we'll look inside the map to pull out all of the data relevant to that state this is going to be val selected data the only thing we need to be careful about here is that if the selected state from the drop down is the all option which is i want to see the data nationally then that element won't exist in the per state daily data and we're going to get a null value here so if that happens we can use this question mark colon operator to say if the value here was null then we would instead like to assign the value of national daily data to this variable now that we have selected data which is our list of covad data across all the days available we can now simply call the method we already have called update display with data with selected data that should be it let's try it out perfect so now we're able to see this drop down and by default the all option is selected which means we're seeing data nationally and then all these state abbreviations are what we're getting back from the api so for example i might look at the california data which is ca and we can see that the data does get updated so the text view down here to show the exact metric value is showing something significantly smaller which is for california and then if i choose different metrics i'm again seeing the california specific data and the same functionality applies across all states i can scrub on the spark view i can change the time scale and i can choose any metric that i want if you've gotten this far drop a comment to let me know so i can congratulate you on building out all the functionality for our application in the next video we're going to make a couple design improvements for example we're going to use one more robinhood library called ticker in order to animate changes to this text view and we'll do a few other design and color improvements in the app at this point we're done with all the functionality of our app in this video we're going to go through a couple of really easy and high impact design improvements first in order to really make our app feel like the robinhood stock trading app we're going to use a library called ticker in order to animate changes into this text view here's the github page for robinhood ticker and you can kind of see what this looks like in this gif we're going to have the same effect for our text view if you scroll down all we need to do to include this is add this into our build.gradle file so this is again going to go into the build.gradle on the app module tap on sync now and then let's go back to github and you can see it's really straightforward to use this instead of the text view we just need to replace that with a ticker view so let's go back to android studio go into activity main and that component that we wanted to replace instead of just being a text view we would like this to be a ticker view so go into the code view go to the very bottom and this is what we want to replace so i'll say ticker view here and then i also want to just update the id and make this particular view just so it's obvious that this is the robinhood ui component ticker view now the only thing we need to do in order to properly use the ticker view library is go into main activity and we we need to set a character list on the ticker view so in the method for setting up the event listeners let's add one more line here which is for the ticker view and we're going to set the character list there's a predefined character list called ticker utils dot provide number list because we're going to be animating over numbers so if we try this now so i'm showing positive cases now i go into the number of deaths so you can see how the ticker view did animate in this really nice way and same thing with negative cases and if i scrub over the spark view you can see as i scroll we're getting that really nice feedback that this number is changing one other quick design improvement we can do is to add a background shading color behind the sparkvue and the time radio group the reason this is valuable is it provides segmentation into our layout and it gives a hint to the user about which components are related to each other the way we'll go about doing this is by adding some padding and margin between the sparkvue and the radio group time selection and then adding a background color to those two components so going into activity on this radio group which sits below the spark view that will add a margin top of 16 dp and we'll also add a padding bottom of 8 dp and for the sparkvue we are going to add a padding on the top of 16 dp along with the padding bottom of 8 db and these are the two components the sparkvue and the radio group time selection on which we're going to have a background color i'm going to assign a background and for now it'll just be color primary but we're going to update this in just a bit once we define the color so i'm going to actually call this color background shade and have the same color be defined here and then let's have android studio help us create a color value resource the resource value i'm going to put in here is this very light gray light blue color that i found and basically what that did if i command click in the color background shade is it added one more color resource in our colors.xml file so if we try this now now you can see we have this background color behind the spark view and the time selection and that makes it easier to comprehend what we're looking at the last major design improvement i would like to make in this video is to improve the ui of these radio buttons in our application the default radio button ui on android i think is pretty ugly so we're going to modify it so it looks and feels like a button i have a separate video which talks about a few of the aspects of what we're about to do so i'll leave a link to that if you're interested but the idea is that we're going to remove this circle icon next to the radio button and add a background drawable which is a shape drawable behind each of these radio buttons so first let's fix the styling for a single radio button how about this negative radio button and then we'll think about how can we apply that style to all radio buttons in our application and i use the word styling deliberately because instead of adding these attributes directly onto the radio button i instead am going to define a style and apply the style onto this radio button so inside of the styles xml file which you should already have in the values directory in resources i'm going to open that up we're going to define a new style here and the name we'll call it custom radio button styles can have parents and parents are basically where are you inheriting all the different attributes and styles from and you can see the android studio is suggesting for us that we have the parent be widget app compat compound button radio button which is what we're going to pick and inside of this style tag is we're going to define various attributes in order to remove that circle that shows up by default on the radio button we're going to override the android button item and we're going to set this to a value of null also why don't we set the text style of the radio button to be bold so i'm going to add this style this custom radio button style on the negative radio button that we had and so i'm going to add the style attribute and then reference the custom radio button style so if we try this now we should hopefully no longer see the circle next to the negative icon yeah and you can see that that is indeed the case and we're also bolding the font like we expect now going back into styles xml let's add one more attribute onto the custom radio button for the background and let's define a drawable here and we're going to create a brand new drawable for now i'll just call this button default and then now let's have introduce help us to create a drawable resource file which is named appropriately the root element let's have that be shape and then tap on ok and so here is where we're going to define different attributes of the background for our radio button things like the corner radius the padding the the shape like whether you want it to be a square or oval etc so there's a few different attributes we're going to find here one which is padding and we're going to have the padding be on all sides 12 dp and then one more attribute we're going to have is a radius of 4 dp a corner radius of 4 dp so if we go back into styles xml the error has gone away and now we should be able to see this button default as the background for our radio button but what we really would like is to change the background based on the state of the button if the radio button has been selected or in the checked state that means it's having an impact on what is being rendered in the spark view we'd like to show it in a different way compared to in this default way just button default the way you can do this is through something called a state list drawable so we're going to have one more state list which is a selector type and the selector is basically going to tell us whether to use one background resource file or another background resource depending on the state of the underlying widget or radio button in this case so i'm going to define another drawable resource and call this button background and android studio will help us to create a drawable resource file but this time the new element will be a selector and the reason we want this to be a selector is because this button background xml is going to select which background we actually want to apply on the radio button depending on the state we only have really two states we care about for the radio button one which is um the default and so i'm going to put that at the bottom of the file and that's what we already defined button default and then if the button is in the checked state that's the terminology for radio buttons if the state checked is true we want to create another drawable for what the button should look like at that point so i'll say android drawable and this is going to be drawable button checked let's have android studio help us this is going to also be of type shape it'll be quite similar to our previous button button by default i'm going to copy over everything here the only thing that will be different is we're going to have a solid color background in the case that the radio button has been selected we're going to define this we'll call it color selected background and let's tap on the red light bulb and create a color value resource so i'm going to put in uh this gray value that i found and then i noticed that i misspelled use android studio to help you refactor this so back in button background let's add the closing tag here and let's try it out so by default we're not really seeing any difference but now when we tap on the radio button you can see that we are swapping out the background to this darker color in the back what we'd also like to do is change the text color so we're going to take a very similar approach for that back in styles xml we're going to define another item which is called text color and this is going to be a color state list resource so i'm going to call this color button text and we're going to create a new color resource file and the root element will be a selector so it's the same concept as a drawable stateless resource we're also going to have color state list resources here by default if the radio button is not selected we're going to go into default case and we're going to pick color selected background so we're going to do the opposite of what we're doing in the case of the button so by default we're going to have the selected background color and otherwise we're going to just use white the state checked is true then the color becomes white let's try it so i tap on the negative radio button and you can see that we are able to properly swap out the text color to make it white and make the background that gray color so the next step is we'd like to apply the same style to each of the six radio buttons in our app so one approach is we could go back into activity main and then copy over this style line with every single radio button but then in the future if we had other radio buttons we'll have to keep remembering to add this style line instead we're actually going to make this part of the theme so we don't even need to include it in any radio button i'm going to get rid of this line going back into styles.xml this style app theme defines the base application theme and you can customize it here so there is a property called radio button style so i'm going to add one more item which is android radio button style and we're going to reference the custom radio button style let's try it so now if we've done the job correctly all six order buttons should be updated to include this new style there you can see we are we are seeing that which is great welcome to the very last video in the covid tracking project series so i want to start out by just doing a really quick design improvement to align the project that we have here with what i showed you in the demo in the very beginning so i'm going to update the color scheme of the action bar color here and the color shown in this notification window both of these colors are defined in colors xml color primary dark and color primary so the color primary i'm going to actually make it be identical to color selected background and color primary dark i'm going to make it a slightly darker gray and because color selected background is same as color primary i'm actually going to just make this a reference to color primary and one last thing in order to make it pixel perfect with the original demo app if we go into activity main we can add a margin top on the sparkvue of 8dp let's try it awesome so now you can see that we've faded out and made the action bar less noticeable so that the main attraction of our app is the spark view and the metric being shown finally the very last code change we're going to make in this project is updating the text that's shown in the action bar instead of saying covet tracker i wanted to say code 19 cases per day so that the user has an idea of what they're looking at so main activity inside of oncreate right after the set content view we can just say support action bar dot title is equal to and we're going to pass in r dot string dot app description the app description is a string resource that we're going to create the resource value will be covered 19 cases per day hit enter support action bar might be null so we're going to wrap that in a question mark and we need to actually get the string value out of the string resource and that's straightforward we just need to say get string and pass in that resource try it all right and now you can see the action bar did get updated properly there are a lot of natural extension ideas for this project for example right now we're only showing us data and u.s states but you might be interested in for example the chronovirus cases in india and that would be a really natural thing that you could build on this app by talking to a different api another thing you might think about is instead of showing the delta per day we might want to see the cumulative data from the first chronovirus case up until today and there's no way to do that now but you might imagine having some sort of toggle and finally we're making a network request every time we open up the app however the data only gets updated once per day and so you can imagine implementing a local database where we cache all the data so you could implement something like a room database in our application store all the data and if you don't have an internet connection or if the api request is unnecessary we can simply grab the data from our database to recap we covered a lot of ground in building out our robinhood style coronavirus tracking app first we used retrofit to talk to the kobit tracking project which is the api which provided all the data for our application next we used two libraries from robinhood in order to build out the core ui of our application first was spark which helped us to graph this spark line chart in our application and showed the growth of chronovirus cases negative positive or debts on a per day basis and the second library was called ticker and that allows us to animate changes in a text view and finally we used another library called nice spinner in order to have a better looking drop down menu a better spinner which shows all the state data and when the user selects a new state we update the ui accordingly if you've been following along and you have your own working version of this chronovirus tracking app i'd love to hear from you in the comments let me know how it went or if you completed any extensions beyond what we built given that google still isn't allowing kobit 19 tracking apps in the play store i really hope that you're able to use this mobile app as a way to track the growth or hopefully the decline of coronavirus over time i'll leave a link to the github repository in the description if you have any questions feel free to let me know and i'll help as much as i can until next time stay safe and i'll see you later byehey free code camp we're going to build a coronavirus tracking app and we'll do it in the style of a really popular stock trading app called robinhood we're going to cover how to use different third-party libraries in your android app we'll talk about method decomposition and reuse and we'll look at how do you make api calls using a library called retrofit covid19 has dramatically changed what any of us thought 2020 would look like and all the data indicates that coronavirus will continue to impact our society in a very meaningful way for a lot of 2021 as well as engineers or app developers the best thing we can do is look at the data for covid19 and understand it and display it to other people so we can all become more educated about this virus unfortunately google play decided to prohibit all kovid 19 related apps unless they're from a government or medical institution so i decided to build my own covid19 tracking app and i'm going to show you how to build it as well our app uses the same ui components as the robinhood stock trading app and the whole app is going to be written in less than 200 lines of kotlin code let me do a demo of the app the purpose of what we're building is to be able to quickly see trends around the growth of current virus both at the national level and state level by default when we open up the app we're displaying the number of positive covid 19 cases nationwide or across the whole us and i have the ability up here to toggle between the number of negative cases per day number of positive cases or number of deaths per day and you'll notice that notice that the graph animates in down here we have the ability to toggle between the different time scales so maximum means display all the data we get back from the api which is generally starting from around march one month means the most recent one month of data in one week means most of the most recent week of data by default we're showing maximum the other option i have is to actually scrub on the chart on this line chart and you'll notice that we update the metric the individual metric number shown down here it animates in and it displays the exact quantity of this metric on that day so on april 25th 2020 though there were roughly 1800 deaths in the u.s i also have the ability to dive into a particular state so for example in california you can see that there's been a recent increasing trend in number of positive cases per day in california and the same things apply i could also dive into the number of negative cases in california or number of deaths and if i wanted to look at a particular day i can scrub over the graph and you can see how the text animates in down here if you keep watching you'll learn how to build exactly this step-by-step the data for our app is coming from the covid tracking project which is the most reliable data source i could find for getting daily updates on the number of chronovirus cases two of the core components in our application this chart which is called a spark chart along with this changing text view called a ticker view both of them are coming from open source projects from the robinhood app both the robinhood app and our app are displaying the change of a metric over time stocks versus chronovirus cases so there's a natural fit to using the same components that they're using in the robinhood app and robinhood is considered one of the best design android apps out there so there's a lot to learn from what they're doing i hope you're as excited as i am to start building this project in the next video we're going to fetch data using retrofit from the covid tracking project api our goal in this video is to talk to the covid tracking project api in order to retrieve the data that we need for our application the way we'll go about doing this is by using the api created by the kobe tracking project our phone or our application is the client and we're going to be making a request to the covet tracking project and getting a response which contains the data we're going to be making a get request on this particular url api v1 slash us daily.json and what that represents is we want to retrieve the daily data of the number of chronovirus cases nationwide and the covid tracking project will respond with json data and that json data will contain the metrics for each day up until the most recent day in addition to getting the data nationally we'd also like to be able to get the per state data for coronavirus and in order to do that there's one more endpoint in the api that we'll need to hit and that will give us back a list of the data per day per state now we have an idea of what we're trying to do we can start the implementation we're going to use a library called retrofit on android which makes working with apis really straightforward what i have here is a totally empty android project so if i run it now you'll see the emulator showing the hello world application the first thing i'm going to do is go into the android manifest file and because we're talking to an api over the internet we need the internet permission in our application let's start typing users permission internet the next step is to include retrofit in our project so what i have open here is the official site for retrofit which is a library developed by square and i'm going to go to the download section so we can figure out how can we include this library into our project so here you can see it says for gradle which is what we're using you need to include this line i'm going to copy this and notice that it says insert latest version here so we're going to fill that in later but i'm going to go into our project and go into build.gradle and make sure you're going into the build.gradle which is located in the app module and then in the dependencies section i'm going to add one more dependency which is for retrofit in order to get the latest version i'm going to open up github and tap on releases and you can see that the most recent release is 2.9.0 so let's replace this with 2.9.0 one more thing that you'll need in order to use retrofit is a converter if i tap on the section around retrofit configuration the converters are used by retrofit to translate the api response into a model that we can work with in our application and i'll talk more about what that means later on we're going to use json for this so i'll copy the dependency for json go back into android studio and paste that in with the same version number as what we used for retrofit finally the last thing we'll need to do before we can build our project is instruct gradle to use java 1.8 and the reason for this is because more recent versions of retrofit use a component which uses a java 8 feature which are lambdas so in order to enable java 8 we go up into the android section of the build.gradle file hit enter a few times and we're going to add a section here called compile options in this section we're going to have two lines one for source compatibility and the other for target compatibility and for both of these the value was going to be java version version 1.8 at this point it's worth making sure that we haven't screwed up yet so i'm going to tap sync now and we see a sync success the next thing is let's build our project and we don't expect any ui or functional changes but we should still be able to build the project and see hello world in order to use retrofit the first thing i like to do is define a new file which is an interface that retrofit will consume in order to talk to our api the way that works is we want to create a new interface file in the same directory where main activity is located let's define a new file here a new kotlin file and call this covid service the idea of this kovic service interface is that we're going to have one function defined here for each endpoint in the apf so like we talked about earlier there are two endpoints that we're interested in one which is for getting the national data per day and i'll call that get national data and the other is for getting the per state data and i'll call that getstate's data plural because we're getting the data across multiple states the way retrofit works is that we need to add in a corresponding annotation for each method defined in our interface so for example we're doing a get request on the endpoint us daily.json for getting all the national data next we'll add a return value for each method that we've defined retrofit and json will automatically take the json data returned from the api and turn that into data models that we can use in our application this is going to be enclosed in something called a call object that retrofit gives to us and then our job is to define the data class that we'll actually be using in our application and i'll call that covet data so we're going to have the return value be a call which is a list of covet data because there will be one element in the data we get back for each day the return value for the other function in our interface is going to be the same a list of covadata and i'll show that to you later and the annotation is going to be similar again except for the endpoint is states daily.json instead of us one thing that's worth noting about this api which is really nice is that there's no authentication or api key that you need in order to use it so now let's define this data class covet data i'm going to again open up the project tool window and let's define a new kotlin file which defines covet data cova data class is going to be a data class which represents the data that we care about from the json object in the api we're going to use a annotation called serialize name which defines the mapping of the json key to the variable that we want to map it to in our data class so for example there's a key in the json object called date checked and we're going to map that to a string which is also called date checked and i'm going to show you that in the actual json result that we get from the api so what i have here is the documentation for the covid tracking project api and if you scroll down you can actually see the different endpoints available in this api the data that we're getting back right now is historic us value and we can issue the get request in the browser in order to dive into the json data and you can see the data that we're getting back is enclosed in this json array that's what these square brackets mean and inside of this json array are different json objects this represents one day worth of covet 19 metrics for the us the covad data class we've defined in our project represents one json object here and the attribute that we've already parsed out is this one called date checked so we're actually parsing out this string we're going to ignore a lot of the attributes in the json object but because we're interested in the change per day the attributes we are going to parse out are negative increase positive increase and depth increase in addition when we are querying for state data we're also going to care about an attribute called state so i'm going to include one attribute in copa data for each of the json keys that we just talked about positive increase negative increase and depth increase in addition we're also going to have one more key for the us state that this data represents one optimization we can do is if the serialized name exactly matches with the name of the variable we can get rid of the serialized name annotation and that's the case for each attribute that we've defined i'm going to go ahead and delete the serializer name for all of them one thing we should fix here is that the positive increase negative increase in death increase won't be of type string but they'll actually be of type integer because they represent the number of new cases found in each of these categories so now we've defined the cova data class we can go back into covert service and we can see that the red underlines have gone away now we can put all the pieces together in main activity the oncreate function will get called by the android system when our application boots up when our activity is being created at that point we want to make the api request to fetch the national data so we can display a chart on the screen showing it we'd also like to get the state data because as soon as we get the state data back we can populate our drop down or spinner so the user is able to drill down into a particular state here's where we're going to use retrofit the first thing we'll do is create an instance of json using the json builder because we're going to need that to create an instance of retrofit we use the retrofit builder passed in a base url which i'm going to do shortly and add in a converter factory where we pass in the json converter factory and pass in the json object and then we can call dot build we can now use the coded service class that we created in order to create an instance of the copied service and on this we can call the methods that we had defined and i'll get to that in a little bit but first let's go back and define the base url as a constant up here so in cobit service we defined the end of the url which is us daily.json and if we go back to the browser you can see that that basically captured this last portion of the url the base url will be everything except for that which will be this portion in the beginning so i can capture that put it here and let's add this in in our retrofit builder let's go back and uncomment this covet service like a national data and i mentioned how in kobit service the return value is not the model data directly but something which is graphed inside of a retrofit call object and the reason for this is because of the asynchronous nature of doing anything with network calls so we get back this call object because that is how we get notified of the success or failure of our api request so on the call object that we get back we'll enqueue a callback and this callback will be parameterized by list of cova data we're going to copy that in we can now override the methods that are required as part of the callback so if i tap on the red light bulb we can have android studio help us implement these members there are two methods on failure and unresponsible override both them and in on failure all we want to do is log an error something went wrong with api call so we're going to put a log.e which means log at error level put the tag and then indicate on failure and also include the throwable t which is included so let's define the tag at the top of the file and my convention for that is always to have the tag name be the class name for the on response method the first thing we'll do is simply log at info level that we entered into the onresponse method and we'll also include the actual response that we get back next the body of the response will contain the list of copa data that we should have been able to parse from the api if this data which represents the national data is null that means we got an invalid response from the server and we should log something at warning level the log.w and just indicate that something went wrong once we've gotten past this if statement we know at this point that our data is valid what we'll do here is save the national data into a member variable which is accessible throughout the whole main activity class so i'm going to define national daily data and define that as a property on main activity and this is going to create for us a late init var national daily data which is a list of coveted data one important point here is that the data we get back from the api starts with the most recent data however for graphing purposes we'd like to start our data with the oldest data first and so we're going to call nationaldata.reverse in order to get the proper ordering for now the only other thing i'll do in this method is add a log statement which indicates that we're going to figure out in a subsequent video how to take this national daily data and display it in a line chart to finish off this video i want to also fetch the state data and then validate that this is actually working what we've done so far is used retrofit to talk to the api and automatically convert the json data we get back into a class we defined called covadata which includes attributes such as a date of when this data is relevant number of positive cases negative cases debts and when we talk to the state endpoint we also want to know the state that this data is relevant for so i'm going to represent this in this light orange blob which has covered data inside of it and it contains a particular date what we just did for the national daily data is we reversed the order of the list that we got back from the api so the oldest covet data is at the front of the list and the most recent is at the end of the list so a similar logic applies for the state data but there is a wrinkle because all the state data is combined in one large list we'll get all the data for all states for may 1st then may 2nd and then and so on and so forth however in terms of being able to graph the data all really care about for example is being able to retrieve all of the data relevant for alaska and so what our job is is to take this big list of data and pull out all the data relevant to alaska and put that into a separate list so the idea is that we're going to take this big list and break it down into a map and that map will have a key of the state and the value will be all the coveted data relevant to that state so with that understanding now we can define the state data so i'm going to do something quite similar so i'll say coverage service dot get states data and cue it and this is actually going to be quite similar so i'm going to initially just copy all this and we're going to leave the log messages here but instead of calling the return value of response.body as national data this should be called states data similar to what we had before we first want to reverse the whole list we get back but then we want to group this large list down on a per state basis we're going to call this nice group by method in kotlin and pass in the argument that we want to group by and that'll be the state attribute of every covat data object so this is actually going to return to us a map rather than a list so i'm going to call this per state daily data and i'm going to create a property inside of main activity so again this property can be accessed throughout the whole class which we're going to use in subsequent videos this is a map between a string which is a state and a list of copa data which is the chronologically increasing cover data over time once we've computed this per state daily data the next thing is we'll want to update that drop down or that spinner with the state data so that will happen in a later video before we try this out the last thing i like to do is make one small improvement if you go back to kova data you'll notice that this attribute date checked is a string however in order to do computation and make it easier to display this date in different ways we would actually like to have this date check to be of type date java util date rather than a string and so in order to make that happen i can define it as a date here but we need to pass in another method in the json builder so json will know how to convert the date string and turn it into a java date object that can be done by calling this method set date format and you pass in a pattern the pattern that the api we're working with complies with is the following so with that we should be able to properly parse out dates all right so now we can finally try this out what i want to do to validate that we have something working is go into the unresponse method and where we have a log statement once we've computed the national daily data let's put a break point right there and now instead of running the app like normal hit this button for debug app so as soon as our program installs and we get into this onresponse method our program should halt execution at this point and so you can see that that happened here we can take a look at what is the value of this variable national daily data that we just computed so you can see that the size of this list is 134 which is sensible because that means that we have 134 days worth of data and if i expand this we should ideally see all this sorted chronologically so the oldest day is january 22nd january 23rd so it is ordered which is great and it goes all the way up until the most recent day so this gives us confidence that we are able to parse all the data properly and you can also see the other values like positive increase negative increase death increase those are also being parsed out properly here now that we have the data which will power our whole application in the next video we are going to build out the ui which will display the chart and the metrics our goal in this video is to update activitymain.xml which defines the ui for our application and update it to include the different components that we'll need for our coronavirus tracker once we've done that in the next video we'll be able to wire things together and actually have the data that we parsed out in the last video together with the ui component that we had in this video and be able to show something on the screen taking a look at the final ui of our application there are a couple different ui components on the screen at the top you have the label for this drop down and they also have a drop down which is called a spinner on android for the purpose of this video i'm going to ignore that spinner and just have the state text view shown there below that we have something called a radio button group and the radio button group contains three different radio buttons and the idea of a radio button is that it acts somewhat like a normal button except for you can only have one out of those three buttons in that group selected which makes sense because we only want to be able to graph one of these metrics in our line chart below below that we have a line chart and in particular this is called a spark chart and we'll talk about how to integrate the robin hood library to include this below that we have one more radio group which has three radio buttons and then finally at the very bottom you have two text views one which is for the date of what metric is being shown then to the right of that we have the metric corresponding to that date here's the default activity main that comes in with any empty project the first thing i'm going to do is delete the default hello world text view and instead bring over one more text view and for now i'm just going to go into the design tab we're going to toggle between the design tab and code tab quite frequently and just to give myself more room i'm going to open up the design tab and make that the only thing shown on the screen so we have this textview on the ui i'm going to call this tv and id of tv select state gives us a text of state and then have it be 16 dp to the from the top and left let's also make the text larger the text appearance large next i'd like to bring onto the screen a radio button group so i'm going to go into the button section and bring over a radio group and then have the width of this radio button group be match parent the whole width let's zoom in a little bit have this be constrained to the bottom of the state text view and then inside this radio group we want three radio buttons so i'm going to take the radio button and drag it inside of the radio group in the component tree the first video button will be radio button negative this will have a text of negative and also let's make the layout with wrap content rather than match parent so it shrinks let's copy over this radio button two more times so we'll have one more for radio button positive the text will be positive and then one more for radio button death in order to have these radio buttons be horizontal rather than vertical we need to set the orientation attribute of the radial group and it looks like the width here should also be wrapped content same as this and then also we want to center the contents of the radio group inside of it so i'm going to select the radio group one more time and set the gravity attribute and have the gravity be center and then apply so now you can see that it is in the center both horizontally and vertically below this radio group we'd like to have a line chart which shows the data on a per day basis so to do that we're going to use a library from robinhood an open source library called spark and this is a library to show a simple android sparkline chart view so if you scroll down to the very bottom then we can copy over this line that we're going to add into our gradle build file i'm going to open up the build.gradle file it's located in the app module add that in and then tap on sync now while that's syncing let's go back to github and we can see how to use this there's a section here about usage all we need to do to include this spark chart in our application is add the spark view to the layout then going back into android studio we can open up the activity main.xml file and to add the sparkvue i want to go into the code tab so if we can just start typing sparkvue here and then android studio will help us with autocomplete the width will be matched parent because we wanted to take up the whole width of the screen and the height for now it's going to hard code in 150 dp and we'll change that later one thing we need to do also is we're going to position the sparkvue vertically below the radio group above it so i added this id on the radio group called radio group metric selection so now we can say the top constraint is to the bottom of the radio group metric selection we'll also give the sparkvue an id of sparkvue so let's see what this looks like in the design tab so you can see that we have a space allocated for the spark view below the spark view we have one more radio group and this is going to be vertically positioned below the spark view we'll give this radio group an id of radio group time selection because it'll be used to select the time range of the spark chart we'll add a 16 dp top margin on the radio group and then we're going to do something very similar to what we had before we add in 3d radio buttons update the text and id and position them so that the radio group is horizontal the three time scales that we're going to allow the user to pick from are the most recent one week most recent one month and the maximum amount of data that we get returned from the covet tracking project api as of today the max will typically be a period of around four or five months because we start getting data back from the api around january or february the last thing we need to do to complete our basic layout is add the two text views at the bottom of the screen and these will be relative to the bottom of the parent or the screen and not relative to the elements above it so we'll drag out a text view have this be 16 dp from the left end of the screen and concentrate to the bottom and let's also give this a height a hard-coded height of 80 dp this will be a text view for the date the date label and let's change the text appearance a little bit to make it body one let's have one more text view which is also 80 dp tall the same exact height and this text view is going to contain the metric value we'll say tv metric label this is going to be relative to the right end of the tv date label and it'll be to the bottom of the parent the gravity for both of these text views is going to be center and this text view is going to extend the whole remaining width of the screen which is not taken up by the first text view let's provide some sample data for each text view for example this metric it might let's get rid of the text attribute and let's use the tools namespace here which is this wrench text and let's put in a sample data point of 4354 just to see how it might look let's make this text bigger we'll say display one as a text appearance so it becomes a lot bigger and then for this text view over here let's also put in a sample date may 30th 2020. our goal now is to have the sparkvue take up all of the height remaining in the screen once all the other widgets are placed so the way we'll do this is actually allocate the widgets above the sparkvue and below the sparkvue and have them be glued to the top or bottom of the screen so rather than having this radio group be relative to the bottom of the sparkvue i'm instead going to delete that constraint the top constraint and have that instead be to the top of the bottom components that we have like that now i'm going to set the bottom of the sparkvue to be the top of this radio group and instead of hardcoding the height to be 150 now we can just say match constraint and that should now fill up the sparkvue to be all the remaining height so now we have completed the basic layout for our covet tracker in the next video we're going to go back into main activity and fill out this to do so we're going to get rid of this to do and actually reference the sparkvue that we put on the layout and populate it with the national daily data that we parsed out from the previous video i'll leave a link in the description to the code we wrote in this video so you can take a look at the raw xml if you want where we left off in the last video is we created the basic layout for our covid tracker application our goal in this video is to populate this graph to update the sparkvue with the data we get back with the national per day data of chronovirus cases in the code what that means is we want to get rid of this to do item and replace it with the actual code to render the spark chart i'm going to delegate the work of updating the spark chart with our national daily data into a separate method called update display with data this will take in as a parameter the national daily data and then i'll have android studio help me to create this method so i'll hit that red light bulb and then create the function inside of main activity instead of calling this parameter national daily data i'm going to call it daily data because we're also going to reuse this method for the per state data this is a list of covada which is a data class that we had defined earlier there are three things that we want to do inside of this method first in order to render data inside of the spark chart we need to create a spark adapter next we want to update the radio buttons so by default the positive cases and maximum time range is selected and third we want to display the metric for the most recent day of data that we have let's start backwards so the first thing we'll do is display at the bottom of the screen the metric for the most recent date again i'm going to delegate the work of this into another function i'll call this update info for date and what we're going to pass in here is a particular day of data and the data that we want to pass in here is the most recent date and because our data is ordered chronologically we can pass in daily data and pass in the last element i'll i'll have android studio help us again to create this method and we're going to call this covet data the parameter so the objective of this function is to update the two text views at the bottom of the screen with the data inside of this parameter so first is the metric we call this tv metric label that's referring to the text view at the bottom right of the screen and the text attribute of this textview is going to be the number of coronavirus cases either positive negative or number of deaths on that particular day for now because we're hard coding in positive let's go with that that'll be covered data dot positive increase and we actually want to format this number with comma so it's more human readable rather than just showing the raw text in order to do that we're going to use a convenient class called number format so we'll call number format.instance.format and the format method on number format takes in a number and it will automatically format it to include the commas and decimals so our covadata has a date checked attribute which is a javadate object we want to take that javaday object and turn it into a nice string which looks something like may 30 20. so the way we'll do that is with something called simple date format and the first parameter here is the pattern of the date so what we care about is the month which will be capital ms so three of those letters so for example if it's marked it would be mar then we have the particular day in the month followed by the year and that's denoted by the lowercase y the next parameter is the we had to pass in a locale we'll put in locale us and we're going to save this in a variable called output date format that we have this output date format we can use that to format the javadate object inside of our covadata and this is going to be a string which we will put into the text attribute of our text view and we called it tv date label let's continue working backwards the next step is to update the radio buttons to select the positive cases and max time radio buttons by default this is actually very straightforward because all we need to do is specify the particular radio buttons which should be checked that's the attribute name to indicate that it should be selected so i'll say radio button positive and that is checked attribute should be true and then similarly for radio button max let's run the app now and see how it looks so you can see as soon as the network requests to fetch the national daily data came back then we execute the logic inside of the update display with data method and that is what is updating the bottom text views with the particular date along with the metric and also these radio buttons finally the last thing we'll do is create a new spark adapter which will instruct the sparkvue in our layout how to render the data contained inside of this list of coveted data so i'm going to pretend like we already have the spark adapter class i'm going to call it covid spark adapter and we're going to construct a new instance of this coveted spark adapter and this will take in the constructor the list of daily data that we have we'll save this into a local variable called adapter and now i'll tap on this red light bulb and have industry to help us to create this class we'll extract it to a separate file in the same package which is fine we can leave the parameter name as daily data and we can see that this file did indeed get generated inside of the same directory same package where main activity is located so we have this kovid spark adapter this coveted spark adapter has to be a subclass or has to inherit from the spark adapter class which came in from the open source library so we're going to put a colon here and say spark adapter and we'll need to import this and you can see that it does come in from the robinhood library and now there's a red underline under the declaration the class kovid spark adapter if we tap on the red light bulb we can see how to fix the problem which is by implementing these three members spark adapter is an abstract class so we need to provide an implementation for these three methods and if we tap on ok android studio helps us by automatically defining these three methods with the proper parameter and return type because we passed in the daily data in the constructor it's straightforward to implement each of these three methods so i'm going to first change the daily data to be a private member variable so i'm going to call it a private val the easiest method is get count because this is simply going to be the size of the list so because it's a one line statement we can use this nice feature in kotlin to get rid of the method body and just say getcount is equal to dailydata.size the idea of getitem is that given an index which is a position in the list of data we would like to return any which means a generic object which represents the data object at that position so again this is actually one line you can just index into the list of daily data so i'm going to get rid of the body of the function and say get item at that particular index is equal to daily data at index finally is get y and the idea here is that given a particular position in the graph we want to retrieve the corresponding value at that position right now we're only going to be graphing the number of positive cases per day so given an index you can grab the corresponding cova data at that position i'm going to put that into a local variable called chosen day data and then our job is simply to return the positive increase that attribute on that covet data the return type of get y is a float but this attribute is of type int and so to create turn it into a float we just call the two float method so we defined the basic working version of the spark adapter we can go back into main activity the error goes away and now we have one more line to write which is we have to grab a reference to the sparkvue and set the adapter property to be the adapter that we just defined that's it let's try it out when the app boots up you can see that we are graphing now in this spark chart the number of positive coronavirus cases nationwide over the maximum time range and at the bottom of our application we're showing the particular data the particular metric for the most recent day now that we have the ability to show one chart on the screen we're going to extend this functionality so that we're able to respond to changes in radio button click in this video our goal is to make this spark line chart more interactive so that we update it when the user taps on any one of these radio buttons for either selecting a different metric to show or selecting a different time scale the way we'll go about doing this is to map the radio button selection to an enum which represents the metric or the time scale i want to create a new class called chart options and this chart options kt file will encapsulate all the knowledge about the different ways we could render this chart this spark chart and there's going to be two enums inside of this chart options class the first will be for the metric being shown and there are three possible metrics that we can show on the graph one is negative negative cases of coronavirus one is positive cases of coronavirus and then lastly is the number of deaths the other enum we'll define here is the bottom row of radio buttons which are the time period over which the chart should display data we're going to call this enum class time scale and this enum is going to have an associated integer which represents how many days does time scale represent i'm going to call this val num date and this is going to be an integer so there are three possible options in the bottom row of radio buttons one is for one week of data and the corresponding enum is seven days for that then we have one month and we're gonna assume that one month is always 30 days and then finally is maximum which means show the max amount of data possible we don't know ahead of time the number of days associated with the maximum time so we're going to instead put a special value which is going to be negative 1. the combination of these two enums metric and time scale cover all the possible ways that our chart our spark chart could be rendering data there's also a notion of our chart having a certain state our chart has to be displaying one of these metrics and it has to be displaying data over exactly one of these three time scales that state will live inside of the adapter for our chart so inside of the adapter class i'm going to define two variables here one for the metric and this is going to be by default showing the positive cases and notice that this is a var not a valve because we do expect that this metric will change over time as the user taps on one of those radio buttons in the top group and there's one more variable which is the number of days ago and this is by default going to be the maximum time scale now that we've defined these two variables our adapter is now aware of what it should be rendering in the spark chart so in the function get y which returns a float of the corresponding metric value at this position at index instead of always returning the positive cases of chronovirus we should instead check the value of the metric variable i'm going to use the when construct in kotlin and we'll return a different value depending on the metric we'll say return when and depending on the metric we'll do something different when the metric is negative then we want to return the negative increase dot to float when the metric is positive we want to do something quite similar except this should be positive increase and then when the metric is death we want to report the number of deaths on that particular day and then later on we're going to use days ago in another function that we override on the adapter there's one more place back in main activity where we hard coded in the assumption of always returning the positive number of chronovirus cases so here as well in this update info for date method we want to again check the metric enum in our adapter and then return the corresponding metric so in order to have access to the adapter inside of this method instead of defining it locally here i would like to make it a property so i'm going to delete the val and now inroadstudio will show me this red light bulb and i can use android studio to create the property for me so now we have this adapter and right here we want to do something quite similar so val num cases should be again something which is based on the adapter dot the metric and if the metric is negative then we want to return the cova data which is a parameter passed in here we want to display the negative increase attribute of this cova data class and then in the case of positive you want to show positive increase and then finally in the case of death we want to show the number of increases in the number of dots so instead of always placing this value in we can instead show num cases we haven't made any functional differences in the app yet because we haven't added any event listeners for when the radio buttons are changed so all that logic for listening to changes in any of the ui elements we're going to put all that in a function called set up event listeners i'll call that method right here set up event listener and we'll define this method inside of mainactivity the reason i'm calling this method here is because we only want to make the ui interactive when there is actually data to show so as soon as we get the success from our api call to get the national data that's when we want to hook up the radio buttons and the ability to actually scrub on the graph before that it doesn't make sense so in setup event listeners there's two things we want to do first is we want to add a listener for the user scrubbing on the chart and second we'd like to respond to radio button selected events i'll leave what to do for the second item because we'll get to that later in order to allow the user to scrub on the chart which basically means hold down on the chart and drag their finger over it the first thing we need to do is set the is scrub enabled attribute to be true and then we need to set a scrub listener on the sparkvue and as you can see here the parameter that we are provided in this set scrub listener is a value which is a value corresponding to one data object in the chart in particular if you go back to the adapter you can see that the item data that we get back is going to be the return value of this function get item and we're turning back the covet data element at that position so going back into my activity i'm going to call the parameter here item data and then the job here is in the body of this function which will be invoked for us we want to update the ui with this information as a sanity check one thing we can do is just check if the item data is indeed cova data which it should be because that's the only thing we're returning but this is kind of a safety check then we can call the method we already defined update info for date with this item data so we're going to be updating that bottom ui component to show the date and the metric at that date let's run this so now if i hold down on the chart and i move along you can see that i am able to have this vertical line show up and as i move it along you can see the values at the bottom get updated so on april 18th i'm able to see exactly the number of positive chronovirus cases nationwide and this makes our application a lot more useful because we're giving the user an ability to drill down into specific days the last thing we'll do before hooking up the event listener for radio button taps is go back into the kovid spark adapter and make use of this days ago property the idea of days ago is that we want to change the time scale of our graph to only show that amount of data the way we'll do this is by overriding one more method in the spark adapter class it's called get data bounce super.getdatabounds this invocation of the parent method which already defines this is going to return to us a rect f or a rectangle composed of float coordinates so i'm going to capture that supervalue into a local variable called bounds and the idea here is that this rectangle defined by bounds will dictate what exactly is shown in our spark chart if you wanted to shorten or expand the amount of data shown in the chart all we need to do is update the left end of this bounds rectangle so we can say bounds dot left is equal to instead of the whole data which is count from basically invoking this function getcount instead of showing the whole amount we'll say count minus seven which means top off everything except the last seven days worth of data the most recent seven days worth of data and this needs to be afloat so we would have to call to float here then we can return these modified bounds of course we don't always want to subtract seven from the count and only show the last seven elements of the list instead we'd like to change it based on this days ago property instead of having seven here we want to get the days ago variable get the corresponding num days property out of that enum and turn that into a float this will work in the case of looking at the last one week or one month of data because the corresponding value of num days will be 7 or 30. however when the max option is selected instead of reducing the amount of data shown by subtracting from count we would instead like to show all the data so that's a special case where we'll say if days ago is not equal to time scale dot max only then do we want to reduce the amount of data shown so if days ago is max scale bounds will actually be unchanged which is what we want now we're finished laying the groundwork for being able to respond to when the user taps on the radio buttons we simply need to modify the metric or days ago enum inside of the adapter now we can go back into mainactivity and write the logic to respond to radio button selected events so let me remove the to do because we're actually going to complete this item right now there are two radio button groups that we're going to respond to the first is the set of radio buttons on the bottom of the screen which is for selecting the time so radio group time selection we're going to set a unchecked change listener so this is going to invoke the body of this function whenever one of the radio buttons in that bottom group has been selected this method that's going to get invoked has two parameters one which is group which we don't care about so i'm going to change that name to be a underscore followed by a checked id and the checked id is the id of the radio button that was selected so the only thing that really needs to happen here is we need to update the days ago property in our spark adapter to be the corresponding value when one of the radio buttons is tapped on so for example if i tapped on the radio button for one week i should set adapter.days ago to be timescale dot week so rather than hard coding it of course we should do this contingent upon the value of checked id so we'll use the when construct i'll say when checked id and if the checked id is r dot id dot radio button week and we'll map that to timescale.week if it's r dot id dot radio button month then we'll set the time scale to be month and then otherwise the time scale is max once we've updated the days ago the only other thing we need to do is notify the adapter that the data the underlying data has changed so the adapter knows to re-render itself the other radio button group is at the top of the screen for displaying a metric so we'll do something quite similar radio groupmetricselection.set on check change listener you don't care about the group but we do care about the checked id so i'm going to do another blend based on the tucked id if the radio button is positive then we want to update the display metric to be positive so i'm going to actually delegate the work of updating the display metric into a method called update display metric and i'll pass in positive here let's also do the same thing for the radio button negative and then finally for death radio button death let's define this method now the only thing that needs to happen here is something quite similar we're going to update the metric variable in the adapter to be the selected metric and then we'll notify the adapter that the dataset has changed let's try it so by default we're seeing the nationwide number of positive coronavirus cases over the maximum time scale if i change the metric to be negative you can see that we are seeing a different chart and similarly with the number of dates i can also do the same thing for showing only a certain period of data so one month you can see that i'm only seeing that last segment and then week i only have seven data points being shown here so that looks like it's working in the next video we'll make a few improvements to the ui when the radio button is selected and we'll add in a spinner or a drop down component at the top of the screen which will allow the user to look at the data for a particular state there are two things i'd like to do in this video one is i'd like to make some improvements of what happens when i change either the metric shown for the spark chart or the time scale shown and second i'd like to include a drop down or a spinner component at the top of the screen which will show all the states and if the user selects a particular state we should update the data shown in the chart for all the covid 19 cases of that state so first one thing you'll notice is that when i change the metric being shown on the graph this bottom component this text view doesn't get updated so we're actually showing wrong information here right this 20 000 is for the number of positive cases of chronovirus on this particular day and not the number of deaths so this should really be updated when this metric gets updated the way we'll fix this is by adding some logic in this method update display metric this method is invoked every time the user changes the metric shown on the graph so what the logic we have here is doing is updating the metric on the adapter we'd also like to reset the number and the date shown in the bottom text views so really what we'd like to do is call the method that we wrote a while ago called update info for date so the idea here is that we want to pass in the last covet data object and have this bottom component show the most recent data the last day of data that we have along with the metric corresponding to the metric passed in here and that logic is already built inside of the update info for data class so you can see that we're already checking the met adapter metric so we're going to show the right value the question now is how do we know what to pass in here the issue is that we need to know what data is currently being displayed in the sparkvue if the data being shown as a national data then we can take the last element of that list of cova data representing the national chronovirus data and pass that into update info for date for date but if we're showing a particular state's data we need to know what state we're showing and grab the last day's worth of data for that state and pass that in so we need to have some way of knowing what is being shown currently to do that we're going to add one more property or member variable inside of main activity i'm going to define a property called currently shown data and this will hold on to the data that's currently being displayed inside of the sparkvue and the reason i'm assigning the value here is because this method update display with data takes in the list of data which is being shown in the sparkvue so we know that this method has to be called at the beginning and every time that the data for the sparkvue has changed currently shown data is going to be equal to exactly the parameter passed into update display data now android studio can help us to define this property create property currently shown data and now we can go back to update info for date and then pass in the last element of the currently shown data one more thing i'd like to do before we try this out is a quick design improvement based on the metric being shown we can display a different color for the chart so i'm going to add a comment here which says update the color of the chart and what we want is there's an attribute on the sparkvue called line color and we want to set this to be equal to some color integer the way you get a color integer is you can say context compat dot get color and you can pass in context which is this and a color resource so there is a predefined colored resources like r dot color dot let's say color accent this will give us back a color inch and i'm going to actually add an annotation here to make it obvious that this variable is of type coloring so we can pass and color into here and then also we can update the text view which represents the metric so we call that tv metric label and we're going to set the text color color inch so now based on the metric we want to show a different color here rather than just the color accent here are the colors that i picked out which i thought were intuitive for each of the metric types negative cases is green positive cases is this orange color and number of depths is this red color so back in android studio i'm going to paste in those hexadecimal values inside of the color resource file so instead of resources values you should already have a colors of xml and we're going to add three more colors here one will be color negative and then this will have a value of the green color then we'll have color positive this has the orange value and finally we'll have one more color representing the death metric this has that red value now now that we've defined these three colors we can go back here and again use the when construct the when statement in kotlin we're going to define a color resource which is the result of this when statement instead of the went statement for each metric we'll map it to the color resource that we had so for example metric negative will map to r.color.color negative positive will be color positive and death will be color depth now we can use the colored res value when we're obtaining the color int using contextcompat.getcolor and finally last thing we can do before we run this is inside of this method update display with data we're calling update info for date we're already calling this method inside of update display metric and we're actually doing other useful things such as updating the line color so rather than calling update info for date i'm instead going to call update display metric and pass in metric positive because that's that's always going to be the default metric shown let's try it so now you can see when we run the app initially we are again seeing the positive cases of coronavirus over the maximum time scale but we have this nice color applied to it this orange color if i change this to be death we can see it gets updated to red and importantly the texture at the bottom showing the exact metric for the most recent day has been updated to reflect the chosen metric the last major piece of functionality for our app is allowing the user to select which state they want to see data for so back in mainactivity this is corresponding to this to do item that we had left in one of the prior videos so we're finally going to do this i'm going to remove the to do and i'm going to delegate the work of updating the spinner with the state names into a method called update spinner with state data and this function is going to take in one parameter which is the list of all the states to show and that will simply be the key set of this map so if you recall the per state daily data is a map of each key being a state and the value being all of the coveted data for every day of that state so now we can have android studio help us to define this method i'll define it in main activity and i'll have the parameter be called state names and this is of type set of string the objective here is given these state names which are a set we want to turn that into an ordered list and we're going to take that ordered list and pass that in as the input to our dropdown component the first let's turn our set into an ordered list where we're alphabetizing all of the states so we'll call state names dot to mutable list so we can actually change and mutate the contents of this list we'll call this variable state abbreviation list and it will contain the abbreviations for all 50 states plus several u.s territories and we want to alphabetize this list so we want states like alaska or alabama to show up at the top and states like wyoming to show very at the very end of this drop down so we'll call dot sort and then we also want to have one special entry in the state abbreviation list which is to represent the national data right we're not going to get that in the set of strings passed in here because this only contains state names so we're going to have to add it manually right here and this is going to be the very first element in our list so i'll add this at position 0 and i'm going to have a special entry which is called all states which basically means i want to see the national data so again android 3 will help us to define this variable all states and this is going to have a value a hard coded value of all nationwide and i'm actually going to define this outside because i can make this a const so what we want to do next is take this ordered state abbreviation list data and add that as the data source to our spinner next we need to add the spinner into our ui so going into activitymain.xml we would like to be able to add a spinner component at the very top of this layout that we're building i'm not a big fan of the built-in android component for this which is this spinner component i think it's really hard to use and it doesn't look that good instead we're going to use a library called nice spinner and this is easier to work with and in my opinion it looks better so let's go down first to how to include this library into our project so inside of the build.gradle file we need to add a dependence like normal but also we should add this section about repositories so i'm going to go into android studio go into the build.gradle file which is located inside of the app module and you probably won't have a repository section here so right after we added compile options let's add repositories and we want to add this maven repository i'm going to copy this line and paste that in and now we should be able to add the dependency and copy this line and paste it in here tap on sync now and hopefully we're able to download this library properly looks like it succeeded so now we can go back into activity main and we can include it in this area that we allocated for it to do this i'm going to go back into the code view of our layout and right here is the label which describes what this spinner is for i'm going to create another component which is called spinner and it should be nice spinner we'll set the layout width to be zero dp because we want this knife spinner to take up as much room as possible the height can be wrap content and we're also going to add a margin start and end there's a few other properties we can add in here ellipse size we're going to ellipses in the end and the maximum number of lines will be one and then the text appearance of what we're showing should be large and now our job is we need to constrain this view appropriately for the horizontal constraint you want the left end of the spinner to be up against the right end of the select state text view so i'm going to say constraint start is to the end of the tv select state and then the end constraint is going to be to the end of the parent because we wanted to go to the end of the screen for the vertical constraint we're going to have the top and bottom of the spinner be equivalent to the top and bottom of the select state text view which is to the left so bottom bottom of and then we want to pass in cv select state and then something quite similar for the top and one last attribute that i forgot to add is something called pop-up text alignment and i'm going to put start here just so that in the drop-down all of the states are left aligned or start aligned so if i go into the design tab now we should see that there is a space allocated for the spinner one thing we can do here is just give this an id because we'll need to refer to it in our main activity.kotlin file we'll call it spinner select now we can go back into main activity and let's reference this spinner that we just added so i'll say spinner select dot attach data source and we'll pass in the state abbreviation list the last thing we need to do to hook it all up is we'd like to be notified when the user has selected another state from the drop down so on the spinner select widget we're going to add a set on spinner item selected listener and this takes in four parameters the only ones that we care about are the parent and the positions i'm gonna put an underscore in for the other params and this will now this method will be invoked every time a new item in this drop down is selected so in order to get the selected state we're going to say parent dot get item at position it'll pass in position and we know that this is going to be of type string our data source for the spinner is a list of string i'm going to cast this as a string and save this as the selected state now we'd like to get the corresponding daily list of cova data for that state so i'll say per state daily data and then we'll look inside the map to pull out all of the data relevant to that state this is going to be val selected data the only thing we need to be careful about here is that if the selected state from the drop down is the all option which is i want to see the data nationally then that element won't exist in the per state daily data and we're going to get a null value here so if that happens we can use this question mark colon operator to say if the value here was null then we would instead like to assign the value of national daily data to this variable now that we have selected data which is our list of covad data across all the days available we can now simply call the method we already have called update display with data with selected data that should be it let's try it out perfect so now we're able to see this drop down and by default the all option is selected which means we're seeing data nationally and then all these state abbreviations are what we're getting back from the api so for example i might look at the california data which is ca and we can see that the data does get updated so the text view down here to show the exact metric value is showing something significantly smaller which is for california and then if i choose different metrics i'm again seeing the california specific data and the same functionality applies across all states i can scrub on the spark view i can change the time scale and i can choose any metric that i want if you've gotten this far drop a comment to let me know so i can congratulate you on building out all the functionality for our application in the next video we're going to make a couple design improvements for example we're going to use one more robinhood library called ticker in order to animate changes to this text view and we'll do a few other design and color improvements in the app at this point we're done with all the functionality of our app in this video we're going to go through a couple of really easy and high impact design improvements first in order to really make our app feel like the robinhood stock trading app we're going to use a library called ticker in order to animate changes into this text view here's the github page for robinhood ticker and you can kind of see what this looks like in this gif we're going to have the same effect for our text view if you scroll down all we need to do to include this is add this into our build.gradle file so this is again going to go into the build.gradle on the app module tap on sync now and then let's go back to github and you can see it's really straightforward to use this instead of the text view we just need to replace that with a ticker view so let's go back to android studio go into activity main and that component that we wanted to replace instead of just being a text view we would like this to be a ticker view so go into the code view go to the very bottom and this is what we want to replace so i'll say ticker view here and then i also want to just update the id and make this particular view just so it's obvious that this is the robinhood ui component ticker view now the only thing we need to do in order to properly use the ticker view library is go into main activity and we we need to set a character list on the ticker view so in the method for setting up the event listeners let's add one more line here which is for the ticker view and we're going to set the character list there's a predefined character list called ticker utils dot provide number list because we're going to be animating over numbers so if we try this now so i'm showing positive cases now i go into the number of deaths so you can see how the ticker view did animate in this really nice way and same thing with negative cases and if i scrub over the spark view you can see as i scroll we're getting that really nice feedback that this number is changing one other quick design improvement we can do is to add a background shading color behind the sparkvue and the time radio group the reason this is valuable is it provides segmentation into our layout and it gives a hint to the user about which components are related to each other the way we'll go about doing this is by adding some padding and margin between the sparkvue and the radio group time selection and then adding a background color to those two components so going into activity on this radio group which sits below the spark view that will add a margin top of 16 dp and we'll also add a padding bottom of 8 dp and for the sparkvue we are going to add a padding on the top of 16 dp along with the padding bottom of 8 db and these are the two components the sparkvue and the radio group time selection on which we're going to have a background color i'm going to assign a background and for now it'll just be color primary but we're going to update this in just a bit once we define the color so i'm going to actually call this color background shade and have the same color be defined here and then let's have android studio help us create a color value resource the resource value i'm going to put in here is this very light gray light blue color that i found and basically what that did if i command click in the color background shade is it added one more color resource in our colors.xml file so if we try this now now you can see we have this background color behind the spark view and the time selection and that makes it easier to comprehend what we're looking at the last major design improvement i would like to make in this video is to improve the ui of these radio buttons in our application the default radio button ui on android i think is pretty ugly so we're going to modify it so it looks and feels like a button i have a separate video which talks about a few of the aspects of what we're about to do so i'll leave a link to that if you're interested but the idea is that we're going to remove this circle icon next to the radio button and add a background drawable which is a shape drawable behind each of these radio buttons so first let's fix the styling for a single radio button how about this negative radio button and then we'll think about how can we apply that style to all radio buttons in our application and i use the word styling deliberately because instead of adding these attributes directly onto the radio button i instead am going to define a style and apply the style onto this radio button so inside of the styles xml file which you should already have in the values directory in resources i'm going to open that up we're going to define a new style here and the name we'll call it custom radio button styles can have parents and parents are basically where are you inheriting all the different attributes and styles from and you can see the android studio is suggesting for us that we have the parent be widget app compat compound button radio button which is what we're going to pick and inside of this style tag is we're going to define various attributes in order to remove that circle that shows up by default on the radio button we're going to override the android button item and we're going to set this to a value of null also why don't we set the text style of the radio button to be bold so i'm going to add this style this custom radio button style on the negative radio button that we had and so i'm going to add the style attribute and then reference the custom radio button style so if we try this now we should hopefully no longer see the circle next to the negative icon yeah and you can see that that is indeed the case and we're also bolding the font like we expect now going back into styles xml let's add one more attribute onto the custom radio button for the background and let's define a drawable here and we're going to create a brand new drawable for now i'll just call this button default and then now let's have introduce help us to create a drawable resource file which is named appropriately the root element let's have that be shape and then tap on ok and so here is where we're going to define different attributes of the background for our radio button things like the corner radius the padding the the shape like whether you want it to be a square or oval etc so there's a few different attributes we're going to find here one which is padding and we're going to have the padding be on all sides 12 dp and then one more attribute we're going to have is a radius of 4 dp a corner radius of 4 dp so if we go back into styles xml the error has gone away and now we should be able to see this button default as the background for our radio button but what we really would like is to change the background based on the state of the button if the radio button has been selected or in the checked state that means it's having an impact on what is being rendered in the spark view we'd like to show it in a different way compared to in this default way just button default the way you can do this is through something called a state list drawable so we're going to have one more state list which is a selector type and the selector is basically going to tell us whether to use one background resource file or another background resource depending on the state of the underlying widget or radio button in this case so i'm going to define another drawable resource and call this button background and android studio will help us to create a drawable resource file but this time the new element will be a selector and the reason we want this to be a selector is because this button background xml is going to select which background we actually want to apply on the radio button depending on the state we only have really two states we care about for the radio button one which is um the default and so i'm going to put that at the bottom of the file and that's what we already defined button default and then if the button is in the checked state that's the terminology for radio buttons if the state checked is true we want to create another drawable for what the button should look like at that point so i'll say android drawable and this is going to be drawable button checked let's have android studio help us this is going to also be of type shape it'll be quite similar to our previous button button by default i'm going to copy over everything here the only thing that will be different is we're going to have a solid color background in the case that the radio button has been selected we're going to define this we'll call it color selected background and let's tap on the red light bulb and create a color value resource so i'm going to put in uh this gray value that i found and then i noticed that i misspelled use android studio to help you refactor this so back in button background let's add the closing tag here and let's try it out so by default we're not really seeing any difference but now when we tap on the radio button you can see that we are swapping out the background to this darker color in the back what we'd also like to do is change the text color so we're going to take a very similar approach for that back in styles xml we're going to define another item which is called text color and this is going to be a color state list resource so i'm going to call this color button text and we're going to create a new color resource file and the root element will be a selector so it's the same concept as a drawable stateless resource we're also going to have color state list resources here by default if the radio button is not selected we're going to go into default case and we're going to pick color selected background so we're going to do the opposite of what we're doing in the case of the button so by default we're going to have the selected background color and otherwise we're going to just use white the state checked is true then the color becomes white let's try it so i tap on the negative radio button and you can see that we are able to properly swap out the text color to make it white and make the background that gray color so the next step is we'd like to apply the same style to each of the six radio buttons in our app so one approach is we could go back into activity main and then copy over this style line with every single radio button but then in the future if we had other radio buttons we'll have to keep remembering to add this style line instead we're actually going to make this part of the theme so we don't even need to include it in any radio button i'm going to get rid of this line going back into styles.xml this style app theme defines the base application theme and you can customize it here so there is a property called radio button style so i'm going to add one more item which is android radio button style and we're going to reference the custom radio button style let's try it so now if we've done the job correctly all six order buttons should be updated to include this new style there you can see we are we are seeing that which is great welcome to the very last video in the covid tracking project series so i want to start out by just doing a really quick design improvement to align the project that we have here with what i showed you in the demo in the very beginning so i'm going to update the color scheme of the action bar color here and the color shown in this notification window both of these colors are defined in colors xml color primary dark and color primary so the color primary i'm going to actually make it be identical to color selected background and color primary dark i'm going to make it a slightly darker gray and because color selected background is same as color primary i'm actually going to just make this a reference to color primary and one last thing in order to make it pixel perfect with the original demo app if we go into activity main we can add a margin top on the sparkvue of 8dp let's try it awesome so now you can see that we've faded out and made the action bar less noticeable so that the main attraction of our app is the spark view and the metric being shown finally the very last code change we're going to make in this project is updating the text that's shown in the action bar instead of saying covet tracker i wanted to say code 19 cases per day so that the user has an idea of what they're looking at so main activity inside of oncreate right after the set content view we can just say support action bar dot title is equal to and we're going to pass in r dot string dot app description the app description is a string resource that we're going to create the resource value will be covered 19 cases per day hit enter support action bar might be null so we're going to wrap that in a question mark and we need to actually get the string value out of the string resource and that's straightforward we just need to say get string and pass in that resource try it all right and now you can see the action bar did get updated properly there are a lot of natural extension ideas for this project for example right now we're only showing us data and u.s states but you might be interested in for example the chronovirus cases in india and that would be a really natural thing that you could build on this app by talking to a different api another thing you might think about is instead of showing the delta per day we might want to see the cumulative data from the first chronovirus case up until today and there's no way to do that now but you might imagine having some sort of toggle and finally we're making a network request every time we open up the app however the data only gets updated once per day and so you can imagine implementing a local database where we cache all the data so you could implement something like a room database in our application store all the data and if you don't have an internet connection or if the api request is unnecessary we can simply grab the data from our database to recap we covered a lot of ground in building out our robinhood style coronavirus tracking app first we used retrofit to talk to the kobit tracking project which is the api which provided all the data for our application next we used two libraries from robinhood in order to build out the core ui of our application first was spark which helped us to graph this spark line chart in our application and showed the growth of chronovirus cases negative positive or debts on a per day basis and the second library was called ticker and that allows us to animate changes in a text view and finally we used another library called nice spinner in order to have a better looking drop down menu a better spinner which shows all the state data and when the user selects a new state we update the ui accordingly if you've been following along and you have your own working version of this chronovirus tracking app i'd love to hear from you in the comments let me know how it went or if you completed any extensions beyond what we built given that google still isn't allowing kobit 19 tracking apps in the play store i really hope that you're able to use this mobile app as a way to track the growth or hopefully the decline of coronavirus over time i'll leave a link to the github repository in the description if you have any questions feel free to let me know and i'll help as much as i can until next time stay safe and i'll see you later bye\n"