Build a My Maps Clone Android App- Kotlin Android Studio Development

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey welcome back my name is rahul and in the next few videos we're going to develop a full-featured android app using the google maps api one of the powerful things about mobile phones is that they're mobile as a result being able to integrate location and map data into whatever you're building can unlock a lot of really cool functionality for example the app that we're going to build this app will allow you to keep track of important places in your life in the process of building this app not only will we learn how to interact with the google maps api we'll also learn how to pass data back and forth between different screens in your app in addition we'll also learn how to save data to a file keep watching so we can build this together [Music] before we start coding there are three things i want to talk about one i want to provide some background on the app and give you a demo second i want to talk about the main concepts we will and won't cover and finally i want to talk about how we're going to build the app and breaking it down into different milestones the first some background the app that we're going to make is a clone of a really popular app made by google called google my maps the idea of this app is really similar in that you can keep track of places that matter to you you can make custom maps to remember your favorite places explore new cities or plan great vacations this app of course has more functionality because it has millions of downloads and a whole team working on this app for example you can do things like search and navigate to places that you can't do in our app but if you're interested drop a comment and we can keep adding more functionality from google my maps into the app that we're building in terms of what you should know before beginning this project i'm building the app in kotlin so having some knowledge of programming will be valuable don't worry too much about the android concepts because i'll introduce them to you as we encounter them in the app if you are totally new to android though i'd recommend that you start with this playlist which i published a few weeks ago around building a tip calculator in android the tip calculator is a really great first app because it's a lot simpler compared to what we're building here so i'll leave a link to this in this in the description if you're interested now i'll do a quick demo of the app so you can see what we're going to build the main screen of the app shows a list of all the map titles so here i already have five maps i'm going to singapore on vacation in a few weeks and so i made one map which is about all the places i want to go in singapore so if i tap on that map you can see we navigate to a map view which shows all the markers associated with this map called singapore travel itinerary i can tap on one of the markers to learn more about what i had written about it so here's sentosa island and then i can tap on another one to learn more about that and the cool thing here is that we have all the functionality of a normal map so i can double tap to zoom i can zoom out and i can pan which just means i can move the map around of course the map wouldn't be that interesting if all you could do is view an existing set of maps we'd like for the user to be able to create a new map and so you can tap on this plus button in the bottom of the screen and give provide a new map title so i'll call this new map california regions and you'll notice at the bottom there's a dialog here which says long press to add a marker if we tap on that this gives us a hint of how we can add more data into this map by long pressing so if i long press i have a dialog that shows up which prompts me to enter in a title and description the one really important thing is error handling whenever you're collecting data from a user you make sure that that data is sanitized and it's well formatted so if i try and create a marker right now for example you'll see that we have error handling which says the title and description must be non-empty i have to input some valid data here so i can say norcal i can say my fave and then i can zoom out a bit oops i'll drop one more pin in socal so the two regions of california this is not my fave now at the top right there's option here to save it and as soon as i save it you can see that we've added one more element into the recyclerview into the list which is the new map california regions and if i tap on that you can see both of the markers that i had added next i'll talk about the main concepts we will and won't cover while building the app the first of course we'll be talking about how to integrate map and location data into your application because the main point of what we're building is rendering a map and showing important places on it second we'll talk about how to navigate between screens in your app with data this is important because pretty much all apps will have multiple screens and you'll need to be able to communicate between them and we'll use android's intent system to do that and third we'll talk about how to persist data so even if the user closes the app they expect that all the created maps that they have inputted into the app will still be there when they come back to it and the way we'll do this is by saving all the map data into a file there's also a few concepts which we're not covering which is good because it'll make our app simpler and we can really focus on the the core concepts so first we're not going to be doing anything with networking or the internet as soon as you introduce talking to an api or a server your app becomes a lot more complicated and second we're not going to be persisting data with the database generally when you have structured data which we are we do have in this app it's recommended that you put it into a database like sqlite however there is some additional complexity that you have to deal with when you work with something like room or other databases so we're not going to be doing that in this walkthrough finally i want to talk about the steps we're going to take in order to build our application the first we're not going to worry at all about actually rendering a map instead we'll just render a list of all the map titles in the main activity next once you tap on one of the map titles we want to navigate to a different screen where we show the map along with the associated data which are the different markers you can see after that we'll spend a few videos doing the creation flow so that's the flow that you enter into when you tap on the plus button on the bottom right of the main activity we'll also spend one video here talking about how do you save all the map data into a file so when the user comes back into the application we can read all that data from that file that's persisted and finally we'll have one video dedicated to polish and animations to make our app feel a lot better you can tell looking behind me i have a bunch of maps that are always in my room i had a lot of fun building out this project i hope you do too as you're going through it if you get stuck anywhere if you have any questions let me know i'm here to help as much as i can don't forget to like and subscribe and i will see you in the next video the goal for this video is to achieve milestone one for building our app which is to display the list of titles of each user map we're going to display this in a recycler view and i have an extensive video about the reason to use recyclerview and what the benefits are so i'm not going to go into too much detail here but if you're interested i'll leave a link to that in the description in order to make this go faster i'm going to provide you with some dummy data so you can have something similar to what you're seeing on the screen here let's start with opening up android studio and create a new android studio project start with empty activity and let's call this my maps as a name the language is kotlin and minimum api level is fine and then tap on finish so initially android studio is going to take a bit of time to build your project the very first thing i like to do whenever i create a new project is just to run the app and make sure that we see hello world properly because that'll give us a guarantee that we're starting at a known good place and anything we build on top of that we know how to get back to something which is working i'm going to tap on this green triangle in order to run the app we are able to see hello world properly which is what we get from the empty activity starter project the next thing i'll do is instead of showing hello world in the underlying view for the main activity which is activitymain.xml we don't want to show hello world we want to show a recycler view and the recyclerview will hold all of the titles of the maps so i'm going to expand this give ourselves a bit more room get rid of hello world and then we're going to drag out a recyclerview so recyclerview needs a dependency so then android can help add that dependency into your build.gradle file and i've noticed sometimes that when you initially drag out the recyclerview onto the view the attributes tab doesn't open up and one way to remedy that that i've found is if you just run the app then enter two picks up the change and then it's able to show you this attributes tab so once you're able to see that then you can set the width and height to be matched parent because we want to fill up the whole view with the recycler view and also will give us an id of rv map so rv means recycler view so now that we have an id we can reference this recycler view inside of main activity so there are two things we want to set on the recycler view one is the layout manager and the other is the adapter i'll leave links to the prior videos about recyclerview if you want a deeper dive but as a quick overview layout manager is responsible for telling the recyclerview how to layout the views on the screen so either in a grid staggered grid or a vertical linear layout manager or a horizontal linear layout manager and the adapter is responsible for taking the data so in our case the user maps and binding it to a particular view in the recycler view in order to make the adapter part work one thing that's obviously very important is the data and in general data is actually really important for any app you build because typically the way you structure your app and the way navigation will work in your app will all really depend on the data so that's something that we're going to define right now so i'm going to change the view of the project to be the android view just because i'm more familiar with that let's find a new package called models and the obvious model that we have in our app is a user map model and the user map represents a map that the user has created this is going to be a data class in kotlin and the idea here is that we want to put the attributes of the user map inside of the data class one thing that every user map must have is a title so we'll say val title and this is going to be of type string and then the second thing a user map must have is a list of markers and each marker really represents a place we want another attribute called places and this is going to represent a list of place and place is going to be another model that we define inside of our models package place if you remember from our demo a place is a marker which is at a particular location on the map when you tap on that we show a title and a description for what is located there so we'll have a title which will be of type string and a description also of type string and then we want to specify the location the location will be represented as a latitude and longitude each of which will be a double great so now that we've defined place we can go back to user map and we should be able to resolve the error now that we have the models defined it will help us to set up our adapter so the layout manager is actually pretty simple let's do that first so all we want to do is set a layout manager on the recycler view so we'll say we're going to use a linear layout manager and by default you pass in a contact which is the activity and it'll be a vertical layout manager by default which is what we want next we want to set the adapter we're going to define a new class called maps adapter and it will take in two parameters one which is a context this and the second which is our data which will be a list of user map so for now i'm just going to pass an empty list of user map and eventually we're going to actually put in some actual data there we can have android studio help us to create this maps adapter class so i want it to be in the same package as main activity that's fine the android studio tried to be helpful and give us meaningful names for each of the constructor parameters it didn't do that great job so let's help it out so the first parameter will be a context which will be of type context and the second parameter will be a list of user maps which we're going to call user maps this is this inherits from recyclerviewadapter and that is parametrized by a viewholder so i'm going to define an inner class view holder which is inheriting from the recyclerview view holder and this needs to match the constructor of the parent class which takes an itemview so now i can reference this view holder here now we're able to implement the abstract methods of the adapter class there are three methods we're going to implement all of them and my personal preference is i like to have the view holder at the very bottom of the class the easiest method to implement is get item count because literally all we need to do is get the size of the user maps that's how many items we have in our recyclerview or in our dataset next is on createviewholder the job here is to inflate the view and wrap that inside of a view holder so we'll say layout later dot from we need to pass into context here and we need to inflate the layout so instead of defining our own custom view we're going to leverage android's built-in layouts so there's one of them which is called simple list simple list item one and so we're going to inflate that view and i'll show you what that looks like in a minute but we're going to wrap the inflated view inside of a view holder on bind view holder the job is to grab the data which is at this position and then attach it or bind it into the view which is located inside of the view holder so getting the user map at that position is easy because we just index into our user maps and then binding it is also pretty easy this is where we need to look inside what is this layout so if i go into the definition of that you can see that it's really simple it's a text view and it has an id of text one and there's some other things like padding and gravity that we don't care about right now basically all this is for our purposes is the text view and we can use that to go a little bit faster at this stage so going back into map adapter we know that the id is text one so now we can grab that text view so we'll say val text view title is equal to holder dot item view and grab that view and in order to reference that id we need to say android dot r dot id because it's coming from android sdk and then we want to set the text attribute of that text view to be the title of the user map okay let's run the app and we don't expect anything really to change because we're not actually providing any data to the adapter but we should see just an empty screen and there you see what we do what we'd like is to have some data to work with it's not that hard to actually generate your own sample data but in order to speed up the process you can feel free to use the data that i provide you so here's a gist from github so tap on raw and you should be able to copy and paste this directly into your main activity file so let me quickly walk you through this so there's a method here called generate sample data which returns a list of user map and all we're doing here is we're using kotlin to make this really concise we have a list of and we're providing a bunch of different user maps and each user map consists of the attributes that we've already defined in our data class so there's a title and a list of places so for example here we have a title of the map as memories from university and we're containing a list of three places brainer hall gates computer science building and pinkberry with a description and a latitude longitude so now we should be able to call this method i'll say user maps and now this can be the data that we pass into our adapter so now that we have some sample data when i run the app again we should now see the titles and there you can see we do and nothing else happens if i nothing happens if i tap on it which makes sense that will be the goal for the next video if you like this don't forget to like and subscribe and i'll see you in the next video [Music] our goal in this video is to pick up where we left off which is showing a list of map titles in a recycler view when a user taps on one of the titles in the recycler view we'd like to navigate to a new screen or a new activity which will render a map with all of the places in that map shown as a marker this is where we're going to be talking to the google maps api in order to be able to navigate to a new map activity the very first step is we need to understand when did an item in the recycler view actually get clicked the way you would typically do this is by setting a click listener on the item view and so you could imagine doing something like this so we say holder.itemvue dot set on click listener and then you take some action so let's just try that so i'm going to define a tag and the tag will be the name of the class that's the convention so now we can say tapped on position so if i open up logcat and we can see maps adapter we do see the taps on various positions what we'd like is main activity to get notified of a tap and the main activity should be the place where we do the navigation to another screen so what we'd like is when user taps on a item we want to navigate to a new activity so the question then becomes we're able to listen for clicks right here you want to notify the main activity when this happens the way we can make this work is by defining interface in the map adapter and passing an instance and implementation of that interface in the maps adapter constructor and so we'll say interface on click listener [Music] and this is going to have one function called on item click it'll take in a position and now we're going to add this as a parameter onto the constructor so going back into main activity we have a error here that we haven't passed in an instance of that interface so let's do that and we need to define an implementation for that method and let's put a log statement here as well so we're passing in an implementation of interface but we're not doing anything with that interface right this is unused so the idea the way this is all going to tie together is when the item view is clicked on we want to fire the method on that interface so we'll say on click listener dot on item click and we'll pass in the position here so now every time a user taps on one of the items in the recycler view we'll call this on item click method which is part of the interface and that will then alert this code to be fired and we'll get this log statement so let's try it so now we expect to see two log statements every time we tap on an item one is from maps adapter and then one is from main activity great so that works once the user taps on an item we would like to navigate to a new activity that'll happen inside of the click listener the way android does navigation to different screens is through something called an intent system if you google for codepath intense you should be able to come to this guide to talk a bit more about what is an intent and why we should use it so intents are fundamental to how android thinks about navigation between different apps and within your app an intent is a message that can be thought of as a request given to either an activity within your app an external app or a built-in service so an intent is a way for your activity to communicate with the outside android world you can use intents to take the user to another screen within your app which is what we're going to do take the user to a particular url within a web browser and there's a few other examples given here there are two types of intents one is explicit and the other is implicit we're going to be using explicit intents because those are used to launch other activities within your app the new screen that we create which is for rendering a map that's going to live within our application that's why we're going to be using explicit intents implicit intents are used to ask the android system to open up any activity that can handle the intent that's described so for example you could imagine i want to make a phone call i want any phone app to handle that request another example could be i want to get a picture so it doesn't matter where i got the picture from but i want to fire off an implicit intent to the android system and the android system will return to me any application that can handle that the way to launch explicit intent which is what we're doing is through something described here so i'm going to go into the kotlin tab we're going to create a new intent object we pass in a context which is where we're coming from and a second parameter of the intent object which is the class we're navigating to so we're going to do something very similar in our main activity so we need to have a class which we navigate to the way we'll do that is open up project and open up the directory where main activity is located we're going to create a new activity right here that's the activity which we're going to navigate to so go to new and go down to activity and go to gallery because we're going to actually create a a new type of activity that we haven't created before called google maps activity so tap on next and call this display map [Music] display map activity and then tap on finish so android studio is doing a couple different things for us here and let me talk you through what it what exactly it's doing first off in the manifest file every activity that's in your app has to be registered in the manifest so the first thing that industry did for us is it added this line so now we have display map activity the second thing it did is it created a new kotlin class called display mac activity which is what we're going to fill out it also created a corresponding layout file called activity display map all it has is a fragment and that fragment is a support map fragment which is what is actually rendering the map and then finally there's google maps api.xml so this is where we need to specify a google maps api key so in order to render a google map in your android application google needs to make sure that you have the proper permissions to do so and they also want to make sure that no one is abusing their service which is the google maps service and so every developer needs to have a google maps api key which you specify here and that's how google can make sure that no single developer is taking up too many resources so by default there's like a dummy key here which we'll need to replace in order to get this working but luckily this process is really simple all you need to do is open this link in the browser and this link has embedded as part of the parameters of the url exactly the kind of key that we want so we're going to be fetching this map from android app which is why we have key type client-side android and it also has a couple other parameters for example here's the package name of our app and there's also a sha-1 certificate fingerprint these are different attributes that google requires in order to verify the authenticity of whoever is making the request so i'm just going to open up this url in the browser on this page we need to register our application for the maps sdk for android in the google api console so either we can take an existing project that we have already or we can create a new project i already have an existing project and i'm going to add the maps sdk to that one so i'll say continue and now it tells us that the api is enabled so now we can tap on create api key and now we can copy this api key that's generated for us so copy that and then close it if you wanted to be more secure you can restrict the key so that only certain apps and package names can access this key but that's all we need i'm going to copy that to the clipboard go back into android studio and then paste it in to this file google maps api now that we have the display map activity set up we need to navigate here so let's go back to main activity and we'll use the content from that codepath guide about creating flows with intents so i'm going to create a new intent object and it takes some two parameters one which is the context so that's the main activity and then the second parameter is the class that we're going to so that will be the display map activity dot java that class and then to actually do the navigation you have to call start activity with the intent so if you try this if we tap on a item in the recycler view we should navigate to the new activity you you see that we do navigate to the new activity but the maps are not rendering sometimes what happens is as soon as you create a new api key it'll take some time for attack to register and become valid so one thing i found which will help the process is just uninstall the app from the emulator and then reinstall it i'm going to go ahead and uninstall it and then let's reinstall the app from android studio one more time and now you can see we do see the maps render properly so let's take a look at the starter code in the new map activity to understand why we're seeing this view if you go into display map activity you can see that we have display map activity and it implements this interface on map ready callback which is why we have this override on the on map ready function basically we have the corresponding layout file which contains the fragment which is a support map fragment we're getting a support map fragment and we're calling get map async and we're passing in the on map ready callback so basically this support map fragment is going to do all the magic of rendering the google maps api and when we want to get notified that the maps are ready to be rendered then it will notify us through this method it's worth noting at this point that in order for your android phone to be using the google maps api it needs to have google play services installed so as you can see from the comment if google play services is not installed on the device the user will be prompted to install it inside the support map fragment so one of the really nice things about using support map fragment is that it takes care of all the complexity of showing a dialogue and an error message to the user if they're on an older version of play services or if they don't have play services installed at all this method the on map ready method will only be triggered once the user has installed google play services and returned to the app here you can see that we're capturing the value of the google google map which is the parameter here saving it as a member variable in our class and then we're adding a marker so here's a marker for the latitude and longitude of sydney australia and we're adding it to the map and then we're moving the camera which means moving the view of the map to be centered on sydney that's why we're able to see this view here so in order to show the data of the user map which is the data from the map that was clicked on we need to actually have access to the user map data inside of this activity the way we can do that is if we go back to codepath we want to pass data to the launch activity and so what we want to do is we want to add extra data into the intent in the way that's being shown here so we'll go into main activity and as part of the intent we want to put some extra data and so typically the way this works is the first parameter will be a string and the second parameter will be the value that you pass in there's a key value essentially the key is always a string and we'll call this extra user map and then i'll define that up here and the reason i'm not making this private is because we actually want to access user map inside of display map activity in order to get the value out and the value of extra user map will be the user map data that was clicked on so we'll say user maps at that position you'll notice here that android tv is complaining it says that there's no such method which takes in a string followed by a user map because the user map is something that we've custom defined the only things that are allowed as the value of a intent data are primitive types such as float int short string boolean things like that or there's also something else called serializable the idea of serializable this is a concept coming from java is that you can take an arbitrarily complex data structure so user map is one example of a data structure which because because it has different data inside of it and you can serialize it which means you can deconstruct it into bytes that you can send back and forth and then you can later on deserialize it so you can take those same bytes that represent the user map and actually reconstruct a user map object and so in order to be able to pass the user map we need to make the user map data class serializable let's open up user map and it's as simple as extending the serializable interface and this interface is empty so actually there's nothing really to do except for extend it and because we're making user map serializable and the place class is part of user map we also need to make the place class serializable as well so now going back to main activity you can see the error went away and in display map activity we can now retrieve the value of this user map so i'm going to save the user map as a member variable i'll say privately init var user map i'll call it this is a user map and we want to get the value of user map from the intent so we'll say you intent dot get extras get serializable extra and we pass in the key which is extra user map and we want to cast this as a user map so now that we have user map let's actually just log something from it instead of on map ready log dot i just as a proof that this is working we will just print out the title of the user map inside of the on map ready callback and let's define this tag okay let's run it now there should be no behavior change other than we should have this log stamp being printed out so i tap on the first element i again see the map view the map activity which is centered on sydney australia open up vlogcat we should see a log statement from display map activity and we do so we have memories from university so this is proof that we are successfully passing data from this activity into the display map activity the goal now that we have the user map data in this activity is we would like to be able to add a marker for each place in our map the way that might work is we say for each place in user map dot places we'd like to do something similar to how we're adding a marker for sydney so first we'll define a latitude and longitude which is based on the position in the map so i'll say place dot latitude and place that longitude and then we need to add a marker by using marker options so we pass in the position which is latitude longitude then we pass in the title the title will be the title of the place object there's also one more field called the snippet which will be the description of the place let's try it so if i go to january vacation planning which has locations from all over you can see that we still have the marker from sydney and then we also have the markers which are legitimately part of the map that looks good so if we get rid of sydney now let's try this one more time so you can see that we do still see the markers and we got rid of the sydney marker however the map started out by looking at the very center uh of the equator and zero zero latitude longitude instead we'd like for the map to be centered and tightly focused on just the area which contains the markers and there's a nice way to do this which is using something called latitude longitude bounds builder so we're going to say that long bounds dot builder this is going to be a bounce builder and the idea is that we want to keep adding latitude longitude positions into this bounds builder include on and now we can do something similar to what we already have with moving the camera map instead of saying new that long balance focus not a single latitude longitude we want to include the whole bounds and this is going to be bounds builder dot build and there are two versions of this method one is takes an additional int which will describe the padding that you want on each of these and the other version takes in three integers which is the one that we're going to use i'm going to pass in a thousand a thousand and zero the idea here is that the markers of your map will take up a certain amount of space if you want to constrain that to be a very small part of the view you can add in uh the bounds of that here by putting in a thousand thousand that's large enough to make it irrelevant so basically we're saying zoom in as much as possible we don't want to constrain the amount of space for the for the bounds in our map and then zero means that we don't want any padding let's try it now okay you can see immediately that the map zoomed in to just the area which contains the markers and if you go into something a bit more precise like just singapore you can see that we are only seeing a singapore area here awesome one more thing just in case you're interested in trying it out there's a lot of nifty methods on the map object that we have here for example instead of move camera i can say animate camera and this does a really nice animation from the beginning until zooming in until you reach the destination which contains all the all the markers that's something you could try out i'll go back to the move camera method just because the animation uh might get a bit tiring if we repeat it too often one last thing we'll do is update the title of the new activity the title of the action bar to be the title of the map and so as soon as we get the map object then we can say get the action bar and set the title to be the user map.title so if we run this now we tap on one of the entries in the recycler view we can see that the top of the activity is now updated appropriately to indicate what we're looking at so we're able now to view a map that we already have but we'd like to be able to allow the user to create a new map so that's the goal for the next video if you're enjoying this please like and subscribe and i'll see you in the next video the goal for this video is to implement the first half of the creation flow which is the way for the user to create a new map we want to add a click listener when the user taps on the floating action button and when they tap on that we go into this view where they can drop markers or pins onto the map and save it the first thing we'll do is add a floating action button in the bottom right of our main activity so the floating action button or fab is the common android way to indicate to the user that there is a primary action for the user to take for example create a new object so the way we'll do that is go into activity main and then just search for a floating action button and then drag that out and you'll be prompted to specify the icon which should be inside of your floating action button i'm going to indicate i want ic input add which is just a standard plus button floating action button also requires a library so android studio will include that into your build.gradle file for you and we're going to constrain this view to the bottom and to the left so i'll make it 32 dp or 32 density independent pixels from the bottom and right and then sometimes floating action i also have this weird bug in indoor studio where it doesn't actually render for me in the preview until i actually run the app so let me see if that works and now you can see that it does show up instead of the plus icon being a green color i'd like it to be white and there's an easy way to fix that there's a tint and you just specify the color to be white and there you can see it updated um the other thing we'll do is change the id i'll just make it fab create map this is how we'll refer to it in main activity so if we run the app just make sure that we're able to see the action button properly yeah we are okay and it is clickable so what we want to do is we want to listen for clicks on that button in the main activity i'll say fab and then on click listener and then first i just put a log statement so what we want to do at this point is we would like when the user taps on the floating action button to navigate to a new activity which is designed for the user to drop pins into the map and save it when that action is done when the user has finished their map and they want to save it we would like for that new activity that we'll create to pass data back to main activity the parent activity and so this is a pretty common paradigm in android apps and so if you go back to the code path guide below where we just were which is a section about passing data to launch activities there's a section about returning data result to parent activity which is exactly what we're trying to do here we're going to be calling a different method start activity for results and that what that's indicating to the android system is that we're starting this activity but we would like to potentially get data back from the activity that we're starting and that requires um passing in a request code and a request code is arbitrary integer which can be used to uniquely identify the request to that activity so let's add that logic so we'll say val intent is equal to intent and then we're going to pass in the where we're coming from which is this and next we want to indicate the class that we're navigating to so for that let's open up the project pane and let's create a brand new activity which we'll call create map activity and again this is going to be map activity so the nice thing is this is going to be a bit faster because we can utilize the same api key that we already used from last time so there's only one file google maps api so there's no need to change that anymore and then if we open up create map activity it has the same exact starter code as what we had seen for display map activity so for now let's just navigate to this and we'll see the same thing which is a marker on the sydney location and i'll say start activity for result and then we'll pass in intent along with a request code and we need to define what this request code is and again like i said this can be any arbitrary integer so i'm going to say 1 2 3 4. uh and so let's not worry at least right now about what will happen create map activity but when creating app activity is done doing its job which is to generate a new user map we want to capture the result of that back in main activity so we can update the recyclerview so the way we can do that is by overriding a method on the activity class called on activity result and this you can see that it takes in a request code a result code and the data which should contain the user map so we'll first check if the request code matches up with our request code and also we want to make sure that the result code is equal to result okay which is the android way of indicating that everything went fine and if so there should now be map information from the data object that we get passed back one more thing we'll do before we run the app is before the user navigates to the new create map activity class we'd like to prompt them to ask for the title of the new user map for now let's not worry about that instead i'll just hard code in the value but the way we'll communicate the title of that map into the create map activity is similar to what we're doing with the display map activity so we're going to put extra and we're going to pass in a string so we'll say intent dot put extra and then i'm going to define another constant called title map title and then with this hard coding some value here and on the other end on the create map activity we'd like to set the title of the support action bar to be the map title that we passed in now we can try this so i tap on the floating action button and now you can see the hard-coded value new map name as the title of our activity the way we'd like for the create map activity to work is the user can long press on any part of the map and that will drop a marker at that location where the user can specify the title and description for that marker for that pin so the way this works is we can add a long click listener on the map and then that will give us the location of where the user did the long press let's add a log statement so we can better keep track of this okay and then whenever the user has made a long press let's just put an arbitrary marker in with some hard-coded title and description information so the position will be the position that the callback here gives to us so the parameter could be that long so that'll be the position and then the title can be my new marker along with the snippet which is a description of a cool snippet let's try it so now wherever we do a long press on the map we should see a marker show up there and if i tap on that marker i see the title and description that we had hardcoded and i can repeat this process as much as i want one of the things we'll want is a data structure which will keep track of all the markers that the user is adding to the map and so that when we save the whole map we should be able to iterate through that and generate a user map from all these markers and so in order to maintain this i'm going to have a variable here called markers and this is going to be a list of marker actually it's going to be a mutable list because we might be adding to it as the user does long presses and initially it'll be empty so every time the user adds them adds the marker with the long press we want to add that to our list of markers this member variable the way we can get a handle on the marker is by capturing the return value of mmap.addmarker and we'll say now markers.add marker one more thing we'd like is to allow the user to delete markers that they've already put on the map and i'm sure there's a better way to do this but one simple way i've found to make this possible is if the user taps on the info window which shows up when you tap on a marker that can be an indication that they want to delete that marker so i'll say mmap dot window click listener and then here we want to delete the marker on window click listener delete this marker this is convenient because the perimeter for this function is the marker that we want to delete so in order to delete this one the first thing we'll want is to delete it from our list of markers so we'll say remove and we want to remove that guy and then we also want to remove this marker from the map and the way that works is you say marker to delete dot remove let's try it it looks like we have an error here i think we need to specify a mutable list of marker and then actually we don't need the type parameterization anymore because that should be inferred from the declaration okay so what we expect now is we should be able to long press and that will drop a pin like before but now if i tap on the window it should delete that marker and you can see it does that properly now we'd like for the user to be able to customize the title and snippet when they're adding a marker onto the map so instead of immediately adding a marker with the hard-coded values instead let's show an alert dialog where the user can input the information they care about so i'm going to have a method here called show alert dialog and this will we're going to pass in the latitude and longitude here because we'll need that when eventually we add the marker and so all of this stuff we're going to move down into the show alert dialog but we only want to do this if the user has tapped ok on the alert dialog and they have the information filled out so to learn how to show an alert dialog open up this guide from codepath called using dialog fragment and then if you scroll down a bit there's a section here about building a dialogue by customizing the available dialog objects that's what we're going to start out with we'll get a new alert dialog builder and we'll set various attributes on that this takes in a context and we will set various options such as title just for now we'll say set messages slow we'll change that later and then we'll set a positive and negative button and when you call dot show this is actually going to now return it to us a dialogue let me clean this up a bit and then what we'd like is we we only want to add the marker onto the map if the user has tapped on the ok button the positive button the way we can set that up is we'll grab the button the ok positive button and i'm going to set a click listener on this and so only when it's clicked do we take this action let's try it so now if we do a long press we should see an alert dialog and it shows create a marker along with the message which is hello and we have the two buttons as we expect if i tap on cancel we don't see a marker but if i do tap on ok we should see a marker show up one thing that i forgot to do is if i tap on ok we should now dismiss the dialog [Music] okay so the next step is instead of just having the hello as the message of the alert dialog we actually want a custom view and the custom view will contain two edit texts these two auto text will be one for the title and one for the description the way we can do that is by calling this method set view instead of set message and this is now going to be the view which contains all the information place form view and then we're going to create this view up here so i'm calling this layout dialog create place and now android studio will help us to create a layout resource file with that name and linear layout is a good root element because it's going to be very simple just two edit text stacked on top of each other so linear layout by default will be vertical which is what we want and then let's add in two edit texts here so the name and then right below that is one more edit text which will be for the description so the first one which currently says name we would like it to say the hint should be title and then the one below that the hint should be description and the id of this one should be et description and this should be et title then one more thing we can do is set some padding on the linear layout at least on the beginning and end so that it fits more nicely with the other dialog but everything else in the other dialog will have some padding i'm gonna search for the padding attribute and then let's just add 15 dp at the start and at the end another thing is because the title is uh more important or more prominent let's make the font of that one bigger i will make it 24 sp okay so we've defined the dialog create place properly so this this works and now place form view it should show up when we are long pressing on on the map yes it it shows up properly one thing looks like a mistake is i changed the hint text of the second edit text so i didn't get rid of the default text which is name so let's go back and and clean that up really fast so the hint should be description and that looks much better so now when we have tapped on the ok button we still don't want to add a marker until we've done some sanity checking on the form so if the user hasn't inputted any title or any description on that marker we don't want to allow them to create a marker or a place in the map at that position so in general whenever you're dealing with user input data you need to be very careful about sanitizing and making sure that data is validated so we're basically doing error validation and form handling right here so what we want to do is check the value of the different attributes in the place form view so the title will be place form view dot find view by id and it's going to be an edit text and the id is id dot title et title and we'll get the text and call tostring on it and this will give us back the string version of the title and we're going to do something quite similar for the description except the id is et description so the idea is that if either the title or description is empty then we should not allow the user to create a marker there so first thing i'm doing is trimming it so that in case the user puts in a space bar there's empty space we still don't want to allow that so then we can at this point say toast place must have non-empty title and description and then if this happens we want to return from this on click listener on the positive button and then let's make the toe show for a long amount of time okay and if that worked so we have a valid title and description we want to update the marker to include these values let's try it so i tap on the folding action button i drop a marker here and i'll say western australia if i tap on ok now i properly see this error message and if i tap in a description now i should be able to submit this marker and then the window as expected does show the values i inputted if i tap on it i'm able to still delete the marker like we did previously okay the last thing i want to do in this video is give the user some education about how they can create a map because it's not that intuitive that you need to long press in order to be able to create a marker and so to do that education we're going to be using something called a snack bar the snack bar if you open up the code path guide is a component which is shown on the bottom of the screen and it contains text with the optional single action these are pretty common as an elegant way to inform the user that something has happened or you want to provide some information to the user the way this works is you say snackbar.make you pass in the parent view and you provide the text and a length so let's do that at the very beginning as soon as the view is created there will say snack bar dot make and then we'll pass in the view and the view will be coming from the map fragment and then here's the message long press to add a marker [Music] and the length of our sniper will be infinite length indefinite until the user taps on the action option and so for us we are going to have an action which just says ok and we won't do anything special when you tap on okay we'll just dismiss the snack bar which is already happening by default the color of the action should be white because by default the snapper will be black so we want it to be maximum contrast so we'll say we'll pass in white and the way we do that is you need to pass in context compat get color pass into context and then actually pass in the color so android dot r dot color dot white and finally we should need to call show in order for the standpoint to actually show up you'll notice here that android studio is complaining that mapfragment.view might be null and so it's recommending that we use this syntax which is saying that we only execute this code if the view of the map fragment is non-null this is an elegant way of avoiding a null check so if we run this now we expect as soon as we tap on the floating action button then we see a snack bar at the bottom of the screen and you can see that we do we see long press to add a marker if i tap on ok it goes away and then we have the same functionality as before so at this point the hardest part of the creation flow is done the next video will wrap up with the creation flow and at that point we'll be almost done with the whole app so if you're enjoying this don't forget to like and subscribe let me know if you have any questions see you in the next video the goal in this video is to finish what we started in the last video which is the creation flow the next step is we'd like to be able to add a save icon in the top right as part of the action bar and when you tap that that is what will trigger collecting all the data for this map this user map data class and passing it back to the parent activity which is the main activity so first let's start with adding an icon into the action bar the way we'll do that is through an android system called menus the first thing we'll want to do is add a new resource directory which will contain all our menus and now we want to create a new menu resource file called menu create map [Music] and we'll fill that in shortly but first let's reference that new menu file that we created the way we'll do that is start typing oncreate options menu and here we need to get the menu inflator and then call inflate pass in the menu resource file that we just defined and pass in the menu which is a parameter to uncreate options menu we're going to define various actions in the menu when one of those is tapped you want to get notified in the create map activity the way that works is by overwriting method on options item selected and here we want to check if the item selected is the save icon okay let's go back into menu create map and fill this out so here you can see that the palette of the options of what we can drop onto the menu is much smaller which makes sense because menus are purposefully constrained and the thing that we're going to be dragging out is a menu item and so by default this will create a menu item which lives inside of these three dots which is called the overflow menu so by default everything will live inside the overflow menu let's give this menu option a different name we'll call it save and i'll give an id of mi save that stands for menu item save we don't want the menu option to live inside of these three dots whether you either have to tap on it and then tap on save instead we'd prefer for the action to always be a first class citizen in the action bar and that's what show us action represents if i expand this you can see there's a couple different options here always means always show this menu item as an action which means it should not go in the overflow menu and will always be displayed in the action bar never means it will always be in the overflow menu if room means if there's enough screen real estate only then do we want to show it as an action and promote it into a top level otherwise it'll live inside the overflow menu we want always because we always want the save option to exist so once i say apply then you can see that instead of the overflow menu now because there are no other menu options the save text shows up as part of the action bar instead of it being text we'd like it to be an actual icon so i'm going to select an icon here i'll just search for save tap ok and now it shows up as an icon so let's go back into create map activity now we can compare the id of the menu item selected with the id of the option we just defined so if these are equal then we have tapped on save and in this case we'd like to return true because we want to stop further propagation of menu options items selected so what we'd like to do here is create a map based on the marker data that we have and then pass that back to the parent activity before we do that again we need to do error handling so if the markers that we've saved so far is empty that means the user hasn't dropped any markers onto the map then we don't want to allow them to save the map they'll say if markers is empty then we want to show a toast and say there must be at least one marker and then we want to return early in that case otherwise what we'd like is to generate a user map [Music] and this takes in two things first it takes in a title and the title we can get it pretty easily from the intent and the second parameter is a list of places so to generate a list of places we're going to iterate through the list of markers and for each marker we're going to generate a place there's a really nice way to do this using something called the map function and what that does is it'll iterate through the a list and it'll operate on each element of that list and transform it in the way you specify so we say markers on map and then on each marker we're going to do a certain action in our case we want to generate a place for each marker so the place takes a title description latitude and longitude and these all will come directly from the marker so i'll say marker dot title and then the description will be the snippet of the marker and then the latitude and longitude will also be coming from the marker dot position and then latitude longitude [Music] so the result of mapping this is we're going to transform the list of markers now to a list of places and that will be the second parameter of our user map so we'll say valve user map and now that we've defined this user map we need to pass it back to the parent activity the way that works is we'll say val data is equal to new intent and we'll pass the user map as extra data onto this intent i'm going to utilize the extra string that we've defined from main activity which is extra user map and then pass in the user map here and finally we'll say set result with activity result okay and pass in the data here then call finish so when we say finish what we're telling android to finish this activity which means the create map activity and go back to the parent activity and we're going back to the parent activity with result okay and with the data which contains user map in it so once this happens we should then come back into on activity result and let's see if we're able to actually get into here so we'll put a log statement and i'll say on activity result with new map and we need to get the user map out of the data so we'll say user map is equal to data get serializable extra and extra user map so here we are looking at the data and getting serializable data out of it using this string which you defined already and this is of type serializable the android system doesn't know anything beyond that it's just kind of a binary blob and we're casting it here as a user map and this is what we're actually going to be able to modify and deal with so we'll say user map dot title okay let's try it so i'm going to create a new map by tapping on the floating action button i'll say hello hello and save let's see if we got anything inside of main activity okay yes we do see on activeresult with new map title new map name a new map name is actually the hard-coded value that we've passed in up here which we're going to change later but this is proof that when we tap on the save icon we are able to successfully get into here and because the markers is not empty we're able to keep proceeding we generate a user map and then we call finish which then goes into on activity results from main activity so once we get the data back in main activity we want to modify the data that's used to render the recyclerview so in order to do that we need to be able to reference the user maps and the adapter so i'm going to do some surgery on this and i'll say private latenetvar user maps i'm going to be a list of user map and then similarly for the map adapter it needs to be its own variable here map adapter okay so now user maps in map adapter are member variables of the class and we can reference them in any method so first thing we'll do is add the user map that we have to the to the list of user maps in order to do that we need to make user maps a mutable list and that means that here we actually generate sample data currently is referring back an immutable list of user maps so first we need to cast it or we need to change it into a mutable list to mutable list and now we should be able to call dot add on this so we'll say user map and finally we need to notify the adapter that something has changed in the data we'll say map adapter dot notify item inserted and the position will be user maps dot size minus one last position is what we just inserted so let's let's try this if we run it we'll do the same experiment as we did before but now when we come back we should see another entry at the bottom and the title of it will be what we've already hard coded which is new map name let's see let's add one arbitrary marker and you can see that we do see new map name if i tap on that where we only had one marker on that map but you can see that it does show up successfully here so let's do some quick updates so first when you go into the create flow you'll see we are showing this dummy marker let's get rid of that i'm going to clean up the comments a little bit as well so we don't want to show a marker at the initial location and right now it's starting out at sydney but just to make it more relevant to where i am let's start this out in silicon valley so the coordinates of silicon valley are 37.4 and negative 122.2 so we can put that in if we try that let's see how it looks initially so there you can see it does center in silicon valley but it's super zoomed out i'd much rather it be zoomed in quite a bit closer so you can at least make out where we're looking and in order to do that there's another method on the camera update factory called new lat long zoom and the second parameter here is you provide a float which indicates a zoom level so i'm going to specify a zoom level of 10. so the zoom level is a number between 1 and 21 where one is zoomed out as much as possible like the whole world and 20 21 is down at the street level so as detailed as you can get so 10 is right in the middle is looking at city level which is appropriate for if you're zooming into silicon valley let's try it okay that looks pretty good so now you can see that we're able to see a bunch of the city's san jose palo alto sf which is the heart of silicon valley one more thing we should do is right now when we create a map we're always seeing new map name as hard coded instead we'd like to be able to allow the user to specify the title of their new map instead of having a hard-coded value here in order to do that we're going to do some we're going to do something very similar to what we've already done with create map activity which is we're going to show an alert dialog i'm going to copy this method and put this in main activity and we're going to have to tweak it a bit so the title of the alert dialog that we'll show is going to be called map title and we're going to have to define a new dialog for this i'll call it dialog create map and then have android studio help us to create this it'll be a linear layout that's fine and this will be a simple edit text there will be a single view so i'm going to have the hint be title and the id can be id title let's make it similar in the other one it will be 24 sp so it's a little bit larger to indicate that it's title and let's also on a linear layout the parent let's change the padding as well on the start and end 15dp okay going back to main activity so now we've defined this custom layout i'll call this map form view just because it's a forum which is about creating a new map and here uh we're going to have a title like we have before and the id is the same but there's no more description so we can get rid of this as part of the error handling so then we can say map must have a non-empty title wait so we only want to navigate to the create map activity if we've gotten here because at this point we've validated the the user has inputted a proper title so here we can do the navigation and then instead of the hard-coded value of new map name we want you want to pass in the title and now all that's left is we need to call show alert dialog and then this doesn't need any latitude longitude so we'll just call it with no parameters let's try it so now instead of navigating directly to the create map activity we should first see a dialog and it asks us for the title so i'll call it my new map and you can see that the title of the action bar does update properly to show my new map and if i indicate something like redwood city is here and then maybe one more for a good measure i'll say san jose is here and save it so now we have this new map show up with the name that i inputted my new map and if i tap on it it does properly show the two markers that i had added now this is pretty great we're able to show interesting data to the user by tapping on one of these maps and the user is actually able to create data by tapping on the floating action button however one of the frustrating parts of the app is that there's no way to currently persist the data right so if i close the app and i open it again you can see that that new map i created which had redwood city in san jose is no longer there so a user may spend a bunch of time creating a new map and expect it to be there when they come back in a day or two to the app but now it's gone and so the next video we're going to implement the persistence part of our application if you enjoyed this don't forget to like and subscribe let me know if you have questions and i'll see you in the next video [Music] in the last video we finished up the creation flow in our my maps application however there was an issue in that whatever data the user creates whatever new map that the user creates is transient in a sense that if the app gets killed then whatever data the user has added into the app will get destroyed and there's no way to retrieve it so our goal for this video is to add persistence into the app by writing the data the map data into a file so for some background on this if you go to google in the search for persisting data code path codepath has a really nice guide which documents the different approaches to persistence in android so first we have shared preferences shared preferences is a way to easily save data as key value pairs so for example if you have the option in your app to customize the background color to make it red or black or white then that might be a good candidate for shared preferences local files is what we're doing and so we're going to be saving arbitrary files to internal external device storage and these last two are dealing with databases the sql lite is the standard database in every android app and that's how you can actually save structured data and orm refers to object relational mapping so it's a wrapper around your sqlite database which allows you to do higher level queries on your data so here you can see some of the use cases the shared preferences like we talked about are used for app preferences like setting background color keys of session information local files are often used for blob data or data file caches such as disk image cache and the last two sqlite databases in orm are used for relational data and so in reality given the kind of data that we have which is a user map and a user map contains a list of places our data is inherently relational so really we should probably be using sqlite database or orm and that actually provides other benefits because we can query for some part of the data it's kind of a hack that we're actually using a local file to store all the user maps but that is going to be much simpler for us the idea is that we're going to take all the data all the user maps that we have right to a file whenever a change happens and when we open up the app for the first time we'll read from that file to show the user a list of all the maps that have been created though there are obvious disadvantages to this approach for example if you have hundreds or thousands or even millions of maps you can very quickly see that there's no way you can store all that data onto a single file it would just be too slow you would want to be able to query and say i want the last 100 or last 20 maps and only show those and in the approach that we have there's no easy way to do that however for our purposes writing to a local file will suit our needs just fine and we're really going to embrace this idea of done is better than perfect [Music] so if we scroll down to the section about local files you can read a little bit more about how we're going to be dealing with reading and writing to a file but the main takeaway is that every app on android will have a dedicated directory where it can read and write files and so if we go to main activity we're going to add some methods at the bottom here the first i'm going to add one which is called private function get data file and the responsibility of this method is to return the file which other methods can read from and write to and so first we'll have a log statement here and this is going to print out the directory where this file lives and the way that works is we are going to get the context so we actually need to pass in the context object here and then get the files directory so files directory is an attribute on the context which is the absolute path to a directory on the file system where files created with open file output are stored so that's what we want and then we want to return a file with that with that directory and then the second parameter of file is uh is a string which is the file name and so we're going to we're going to define a file name at the very top so we'll say private const val file name and this is going to be a file called userdata.you maps dot data and this can be kind of whatever file name you want okay so now there's going to be two more methods one which will be for reading the user map data from the file and the other which is given the user map data we want to write it into the user maps dot data file so the first one which is reading from the file that is the process of deserialization and writing to a file is called serialization [Music] user maps and this will take in two parameters one which is the context because we'll need to be calling the git data file method and second is the user maps that we want to write out so we'll say user maps this is going to be a list of user maps okay and so here we want an object output stream and this takes in a file output stream the idea here is that we want to get the file output stream and pass that to an object output stream so that means we can take an arbitrary object and write it to the file and the thing that we're writing is user maps and the reason this is possible is because user maps is serializable we implement that serializable interface so basically you can think of this as taking a data structure or an object and then breaking it down into its component primitive parts this is going to write out some binary data some byte data there's one more method which will be private fun deserialize user maps and this takes in one parameter which is the context but it'll actually have a return value which is a list of user map so here let's also do another log statement just so we know when it's getting called and then we'll call getdatafile with the context let's capture the return value into datafile so if the data file doesn't exist that's the first thing we should check right if the very first time you open up the app and we try to read from the file the file won't even exist so in that case just return we don't want to return any any data so let's just have a log statement for that otherwise the data file does exist so we want to read all the information from the from the file and create a list of user maps from it and the way we'll do that is essentially the opposite of what we have in line 95 the object input stream and then file input stream and here we want to pass in or we want to call the read object method on the on the input stream and then we'll cast it as a list of user map so the only thing left now is call these methods at the appropriate time so deserialized user maps should be called whenever we want to display the list this happens at the very beginning when the app is being booted up so i'll call deserialize user maps and this will return to us a bunch of user maps and we'll add these all into the list of user maps that we already have and we need to pass in the context for deserialized user maps the other method serialized user maps should be called anytime any of the data around the maps changes so in our application the only time that happens is when the user creates a new user map so in particular that happens right here in on activity result we get back a user map and we are notifying that a new user map has been inserted so right here we would like to call the method serialize user maps with the context and the updated list of user maps which has the newly created one let's try it and i'll open up logcat and let's look at main activity logs so when we start the app the very first thing we try to do is deserialize user maps and that will look in this directory data slash user zero that's package name slash file so that's where all the files will live of course right now the data file never has existed so we get that log statement if we now try to create a new map i'll give this a title of california i'll call this silicon valley home of tech giants and then let's put one more in santa cruz well let's let's save it okay so we do get the new map for california created and let's take a look at the the logcat output so we have on activityresult this is from before so we have a new map with title california then we're calling serialize user maps and so here is where if everything works worked properly we should have outputted the entire set of these maps into that file so one way to test this is if i kill the app now and i open it up again that new map called california should still survive and you can see it it does show up and and the reason we're seeing duplicates of these other maps is because when we first create the activity we're getting a sample data and then on top of that we're adding the previously saved maps so now we don't need the sample data anymore so let's get rid of that and actually we can just combine these into one statement so here all we we're not looking at the sample data at all anymore because we've saved all sample data into a file and here we're just deserializing all the contents in that file into a mutable list and we're making that the member variable user map which is how we're displaying the recycler view so if you try it one more time now we should see just the five virtual maps plus the map i just created called california adding persistence into the app makes it way more usable because now all the time i spend to create my own maps can actually survive and i can reference them later on in the next video now that we're done with all the core functionality we're going to add some polish onto the app and also do a high level review of everything we've covered don't forget to like and subscribe let me know if you have any questions see you in the next video if you've gotten this far you've built out a really full-featured inroad app we allow the user to view the map that they've created and also allow them to create new ones and we're saving these to a file so that we have persistence the goal for this video is to polish the app and also do some concept review in terms of polish i had two ideas of simple things we can do which will improve the design and the look and feel of the app first you'll notice that if i tap on the floating action button you can see there's some sort of ripple animation where the background of the button becomes a little darker and this gives the user a really nice feedback mechanism that they've tapped on it i'd like the same thing to happen when i tap on one of the recyclerview elements right now i don't get any kind of feedback the way we can make this work is by opening up maps adapter and right now each view in the recyclerview is an inbuilt simple list item one which is coming from the android sdk all this is is a text view instead we can create our own layout and we can apply some styling on that to have this background effect so first let's go into the layout into resources layout and define a new layout resource file i'll call it item user map and the root element can just be a text view okay so some of the tweaks we can do here is the id let's give it an idea of tv map title width of match parent is fine but the height should be wrap content it should just be tall enough to fit the contents let's give it some sample text we'll say singapore and then let's make the font a little bigger and also let's add some padding i'll put 10 dp of padding all the way around so if i apply it on on this that means it's saying apply 10dp on all four four sides and finally in order to have that selectable background for that ripple animation the way we do that is by specifying a background to get a bit more context google for codepath ripple animation and you can check out this codepath guide ripple touch fact was introduced with android 5.0 um api level 21 which is a few years ago now most phones should be running 5.0 or higher and that's what gives us this nice effect of giving the user feedback of wherever they tapped on the button the way we can make this happen is by having a selectable item background as the background attribute so if i go into here and i search for background and then i search here and then just search for selectable item background and it should show up so now if we reference this newly created text view layout in the adapter we should see the animation so the item user map and we need to make sure that we update the reference here because the id has changed so we call that id tv user map tv map title let's try it and we also expect the text to be larger now okay so it does look bigger just good and if i tap on one of these you can see that we do see the background become darker which feels a lot nicer to the user i get a lot more intuitive sense of what's happening the other improvement i like to make is an animation right now when i tap on the recycler view when i go into the detail view there's not really a clear activity animation from one screen to the next screen but android has really nice support for this so if you go to the code path guide about animation there's a section here about activity transitions so all you need to do in order to uh create these screen animations is call this method override pending transition after you call start activity so let's let's try that um so in domain activity wherever we call start activity which is here i'm going to call override pending transition and this takes in two parameters the enter animation so the new activity which we're navigating to how does that enter and the current activity which is being exited how should it exit and so android has a few built in so let's try those initially so for the enter animation i'm going to just try out the slide in left and then for the exit animation i'm going to try out the slide outright let's try it so now we expect something unique to happen something different to happen when i tap on this in order to get to the detail view so you can see how the main activity kind of moved out to the right and it feels like the map activity took its place by sliding in which is pretty cool however at least for me what's intuitive is the master view which contains the index the list of all the views should slide out to the left and the entering view should come in on the right side so i actually would prefer that these are flipped so in order to do that i'm going to copy this and just tweak it to fit that requirement so i'm going to copy this we're going to create a new resource directory and this is going to be of type animation so we're going to create two animation files which are going to mirror the built-in ones side and left and slide out right but they're going to be opposite so we're going to have slide in right instead of side and left let's put this in and in order to make it slide in from the right instead of left we need to start the x delta at 50 and then move to the neutral position so what this is saying is start from this position and end to this end at this position so instead of starting at negative 50 which means we're starting off the screen to the left and going into the center of the screen we instead want to start off the screen to the right and then come in to the neutral position and then we want something similar for a slide outright so let's copy this slide out left then similarly we're going to start at the neutral position and we want to move left instead of right so the only two they need to make is the 2x delta should be negative 50 instead of positive 50. so now that we've defined those we can start referencing them here so i'm going to get rid of the android prefix and then i'll say slide out left and then slide in right so let's try this one more time so we should see an animation where there's the main activity which has a recycler view should move out to the left and the map activity should come in following that in some ways replacing it coming in from the right nice so you can see that it does that and that at least to me it feels really natural that we've selected something in this view and then we're naturally sliding in to figure out to learn more about what's inside of that that map like usual there are a ton of extensions that you could do now that you've built out the base implementation first the map creation should start at where you're currently located so right now we're always hard coding this to be silicon valley but it probably makes more sense to drop the user off where they're currently located because that's more likely where they're going to be creating maps another extension you could do is show more info about maps in that initial recyclerview screen so right now we only show the map title but you could imagine how it could be really valuable to show the number of markers for example or if you wanted to integrate users you could have the username of whoever created that map in the recyclerview then one more idea i had was store the data on a server right now as we talked about it's kind of a hack that we're storing things in a local file and you could change it into using a sql lite database such as room but another extension you could do on top of that is actually putting the data on in the cloud in a server somewhere using firebase or parse or whatever you want to use and that could unlock a lot of functionality with being able to share your map with other people so those are just a few of the ideas i had let me know if you have any other ideas and if you implement any of them definitely drop a comment and i'd love to check out what you make so there's a lot that we've covered in these set of videos first of all we use the recyclerview to render the list of map titles on the main activity when you tap on the floating action button we navigate to a new activity and all the navigation is happening through the intent system on android and that brings you to this screen and we're using a menu in order to show the save icon then of course we're using google maps api in order to render a map and we're using different operations on the map object such as on long press listener or on window click listener in order to be able to drop pins and leave details about each marker and finally we're using input and output streams in order to take all the map data and persist it into a file i hope you had fun building out this application i'd love any feedback whether you got stuck at a particular place or if you just built out a really cool map and you wanted to share i'd love to see it that's all i had for now don't forget to like this video subscribe to my channel and i will see you next time
Info
Channel: Rahul Pandey
Views: 11,011
Rating: undefined out of 5
Keywords: android, androidstudio, development, programming, kotlin, code, tutorial, rahulpandey, rahul, pandey, teach, codepath, maps, google, intents, navigation, persistence, android google maps, android my maps clone, android my maps, andorid google maps, andoird google maps
Id: 5dBnunaRkq0
Channel Id: undefined
Length: 104min 2sec (6242 seconds)
Published: Mon Oct 12 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.