Flutter: Advanced Maps with Bloc
Map operations used too much to mobile apps while using maps usually need these opinions; marker, line, cluster, distance and tracking.
We will talk four topics today:
- Cluster
- Line
- Points
- Distance & Live Tracking
Maps operation does not support small features, sometimes this operation is bigger than application logic. For example; Google Maps, Uber etc. These apps have the main feature using maps and show interaction to the user, so maps never just map. 😜
Okay, We ready to use maps but which ones do we have?
- Google Maps ( almost apps using this)
- Apple Maps (only has apple users)
- Open Street Map (osm has many options(order, cluster or radius) than others
I used Google Maps, so it’s swift and maps capacity bigger is bigger than others. Flutter has a google map package, and you can use a directly official package of google developers.
I prefer cubic(bloc) pattern for state management so we while writing maps features, we will learn to use cubic pattern apps.
Requirements
- Project need google maps key and write this key on the apps. (You should follow these steps then complete configuration)
- If you are first using the bloc pattern, you should read this portal.
- The project needs some coordinate for a draw to screen. I created this sample API using to firebase rest solutions.
Let’s write together our features.
Service
We use the service manager for all map requests. I used to vexana library network layer, so this manager takes all data to my services. I always create an abstract layer for my service class, and this class gives me an advantage (like a control, safety etc.)
I was creating map service class inheritance from this class.
Now, we have a map service class. This class fetches all coordinates to show maps. I made coordinates or routes service for use this.
Cluster
Sometimes, your application has a lot of coordinates show to the screen if you don't use cluster design, the map screen very confused and marker appears intertwined.
We did a clustering algorithm then listen to map zoom gesture. Your pinch gesture has started to move; your cluster algorithm calculates the maker close to each other, so you have new markers. Now you have new markers; it’s created for near coordinates so draw to number circle to the map screen.
Firstly, let’s make cubic structure for cluster view.
I control to cluster screen with using these states. These the main goals fetch coordinates, draw markers, google maps, initialize.
Cluster Cubit for a user network request and MapsCluster Cubit control to cluster draw logic.
- ClusterCompleted and ClusterError for a created service call.
I was fetching coordinates with this function and initialize map cluster other function.
MapsClusterState is work to screen design. This state needs coordinates and will create markers for the show map screen. It’s a class goal: initialize map instance and update markers.
We defined markers, map, coordinates and fluster instance, so screen using markers and showing marker pin.
It’s an initialize map instance and create markers. ClusterManager calculates and draws new pins to the map screen.
- These very important here, so functions trigger to user zoom then calculate new clusters.
- It’s completed after we call MapHelper, it’s calculated and return new markers list.
- We notify the new list to the UI screen and screen draw the new markers.
- I was using fluster for cluster pattern and I created a manager class for using this package.
Let’s coding to cluster screen:
- GlobalKey provides to scaffold state. We need to key for show error dialogue.
- We use to maps cluster state and draw a new design for every state.
- The listener closure is listening to state and we listen to error state then show an error to screen.
- Cubit class has return firstly initial state and we call the fetch all coordinates, completed state draw to map and cluster functions.
We made to cluster screen when fetching data to services.
- I used to BlocConsumer, and it’s listening MapClusterState draw to new markers instance.
- It sends controller ınstnace to cubit state and calls markers point.
- This code has an important point: call to update markers when camera starting the move and draw a new circle on the map.
It’s done, you can use clustering to maps.
Custom Map Marker Manager
I was thinking “how can I draw multiple markers?” and I want to draw only one time so I write marker manager manage with provider package.
It was control markers in state and if doesn’t find any marker, it will create a new marker and it’s added global map marker state.
Line
Our other options are line algorithm to map. It’s more polyline means the literature. I was fetched the coordinates on my services then I put it markers on the map. It needs to relations to places, so maps have polyline options. We convert each coordinate to PolyLine object after drawing to line related to the screen.
It has an important point: it was drow to line routes but we didn’t know how many have a line points. You should think “Why need to line station?” because we draw to line number from the beginning point to end. if I knew points count, I will make a circle over the points.
Some places coordinate made five points but some places made more points. If you use asset(like a number png), your need png images each coordinates point. I was made to dart code and create a singleton pattern for number circles.
Singleton points draw to circle number and storage to memory, it draws once for each marker point circle.
Let's write to code, firstly I’ve created a cubic state for screen and management all situation.
It’s state inheritance from equatable and it compares other states with selected properties. It’s likely other map cubic states, it’s main difference selected markers zoom and selected line size.
- It’s a draw to marker object with marker manager. Marker manager call to number point to own state. If it doesn’t any points, it creates a new number circle in memory and returns this number points icon.
- Update markers method is making a big line size according to others line.
- Cluster manager in the global context, you can use everywhere. I used provider to global context management.
One minute: we using to cubic for state management then why use provider? The provider gives control and management very simple global context to us.
We have state control structure so I create to screen now.
- It’s drawn to screen for PointState and listen to error point state.
- It has listened to points while fetching complete and draw list screen or error text.
- Scaffold key control to scaffold state and show to error snack options user screen.
The turn draws to line on maps and places card views.
- I was using the stack widget because my place coordinates draw to the front screen.
- I send google controller to line cubit and draw markers now.
- Polylines need points and I calculate from init controllers so I can create polylines. Selected line purpose of thicker this line.
- Camera position needs to show when first loaded.
Finally, line design completed.
Circle Point
Circle point view like a line design this different just only markers show. Let’s look at cubic state and UI screen code.
It has some difference according to that other:
- ChaneSelectedCordinate copies coordinate items to the previous state and it’s sent to a new state.
- User send changed index from page view changed function.
It’s listening to the cubic state and notify the selected place card. That other features like polyline state.
Distance & Live Tracking
We prepared important maps features now. Sometimes, you need user distance for any place or live track user position to show screen. Geolocator package is a very useful package and easy to use.
I created a route manager maybe for different needs features.
If I need live tracking, geolocator has a listen maps change options so you just call google map called for the new value.
getPositionStream(forceAndroidLocationManager: true, desiredAccuracy: LocationAccuracy.bestForNavigation) .listen((Position position) { googleMapController.animateCamera(CameraUpdate.newLatLng(LatLng(position.latitude, position.longitude)));
});
Don't forget to define my location enabled property to true.
- My location button listening device location and update marker circle to maps.
- Other fields look like what we’ve done so far so it has not any new features.
And everything it’s okay. We talk about many map features and we know how to implement features to own projects. It’s very important to point is you learned to use the cubit(bloc) design pattern again in your own project.
See you again in new articles, good luck ☘️