This tutorial is a continuation of Google maps in android apps tutorial and shows how to use MapView instead of SupportMapFragment to display Google maps in android applications. It also covers Google maps UI controls or settings, gestures, events and lite mode topics which were not covered in the previous tutorial Google maps android tutorial. You can find initial setup required to use Google maps android API in android projects at Google maps android tutorial.
If you want to learn android and its latest features with examples. Please visit android tutorials to learn android concepts, components and libraries with examples.
To display maps in your android app, you need to first add MapView to activity layout.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.gms.maps.MapView
android:id="@+id/map_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar">
</com.google.android.gms.maps.MapView>
</android.support.constraint.ConstraintLayout>
In the activity, get the MapView object and call getMapAsync on it passing OnMapReadyCallback handler. And also you need to make sure that you call onCreate, onSaveInstanceState, onResume, onStart, onStop, onPause, onDestroy and onLowMemory methods on MapView object in the corresponding activity lifecycle methods.
In the OnMapReadyCallback’s onMapReady method you can get GoogleMap object and apply required settings to customize the map.
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
public class MapViewActivity extends AppCompatActivity implements OnMapReadyCallback{
private MapView mapView;
private GoogleMap gmap;
private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapview_layout);
Toolbar tb = findViewById(R.id.toolbar);
setSupportActionBar(tb);
tb.setSubtitle("MapView");
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
}
mapView = findViewById(R.id.map_view);
mapView.onCreate(mapViewBundle);
mapView.getMapAsync(this);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
if (mapViewBundle == null) {
mapViewBundle = new Bundle();
outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
}
mapView.onSaveInstanceState(mapViewBundle);
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onStart() {
super.onStart();
mapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mapView.onStop();
}
@Override
protected void onPause() {
mapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mapView.onDestroy();
super.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onMapReady(GoogleMap googleMap) {
gmap = googleMap;
gmap.setMinZoomPreference(12);
LatLng ny = new LatLng(40.7143528, -74.0059731);
gmap.moveCamera(CameraUpdateFactory.newLatLng(ny));
}
}
You can enable UI controls such as compass, zoom controls, indoor level picker, and map tool bar by setting related attributes in xml or programmatically. By default UI controls are not displayed.
Compass will be visible on rotating the map.
Map toolbar will be visible on touching a marker. Map tool bar contains actions which take you to directions screen, google map app etc.
Indoor level picker is applicable for building with floor plans, which allow you to see floor plan of selected level. First you need to enable indoor maps by calling setIndoorEnabled and setting it true on GoogleMap object.
mMap = googleMap;
mMap.setMinZoomPreference(12);
mMap.setIndoorEnabled(true);
UiSettings uiSettings = mMap.getUiSettings();
uiSettings.setIndoorLevelPickerEnabled(true);
uiSettings.setMyLocationButtonEnabled(true);
uiSettings.setMapToolbarEnabled(true);
uiSettings.setCompassEnabled(true);
uiSettings.setZoomControlsEnabled(true);
LatLng ny = new LatLng(40.7143528, -74.0059731);
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(ny);
mMap.addMarker(markerOptions);
mMap.moveCamera(CameraUpdateFactory.newLatLng(ny));
By default user can tilt, pinch to stretch, zoom, rotate and scroll map. If you don’t want to provide these options to user, you can disable any or all of the gestures. Below example shows how to disable gestures by calling setRotateGesturesEnabled, setScrollGesturesEnabled, setTiltGesturesEnabled and setZoomGesturesEnabled methods on UiSettings object.
UiSettings uiSettings = mMap.getUiSettings();
uiSettings.setRotateGesturesEnabled(false);
uiSettings.setScrollGesturesEnabled(false);
uiSettings.setTiltGesturesEnabled(false);
uiSettings.setZoomGesturesEnabled(false);
You can change the camera position programmatically or in xml. Some of the camera position attributes are target position, bearing, tilt and zoom. Bearing is the direction the camera is pointing, which is in degrees clock wise from north. Tilt is camera angle in degrees from the line when it is directly facing the earth.
Classes which are used to configure camera position are CameraPosition.Builder, CameraPosition, CameraUpdate and CameraUpdateFactory. Using CameraPosition.Builder, you can define camera position and then you can apply new camera position to GoogleMap using moveCamera method which takes CameraUpdate as parameter.
To get CameraUpdate object, you need to CameraUpdateFactory and its methods. If you use CameraPosition.Builder and create CameraPosition, you can get CameraUpdate object for that using newCameraPosition method of CameraUpdateFactory.
You can update camera position in response to events. Below example shows how to update camera position.
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
LatLng ny = new LatLng(40.7143528, -74.0059731);
CameraPosition.Builder camBuilder = CameraPosition.builder();
camBuilder.bearing(45);
camBuilder.tilt(30);
camBuilder.target(ny);
camBuilder.zoom(15);
CameraPosition cp = camBuilder.build();
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cp));
}
Camera position can be updated in response to events, below example shows zoom change in response to OnMapClick event using OnMapClickListener as shown below.
gmap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
if(MapViewActivity.this.cameraPositionUpdate){
MapViewActivity.this.cameraPositionUpdate = false;
gmap.moveCamera(CameraUpdateFactory.zoomTo(18));
}else{
MapViewActivity.this.cameraPositionUpdate = true;
gmap.moveCamera(CameraUpdateFactory.zoomTo(15));
}
}
});
There are several event handlers which you can implement and add to GoogleMap to provide custom behavior in response to user interaction on Google maps.
OnCameraIdleListener’s onCameraIdle method is called after camera moves. You can add the listener to GoogleMap object by calling setOnCameraIdleListener.
gmap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
@Override
public void onCameraIdle() {
Toast.makeText(MapViewActivity.this, gmap.getUiSettings().toString(),Toast.LENGTH_SHORT);
}
});
OnCameraMoveListener’s onCameraMove method is called while camera moves. You can add the listener to GoogleMap object by calling setOnCameraMoveListener.
gmap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
@Override
public void onCameraMove() {
//do something
}
});
OnCameraMoveStartedListener’s onCameraMoveStarted method is called when camera motion starts. You can add the listener to GoogleMap object by calling setOnCameraMoveStartedListener. Based on the reason for camera motion, you can do something. Possible reasons for camera motion are GoogleMap.OnCameraMoveStartedListener.REASON_API_ANIMATION, GoogleMap.OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION and GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE
gmap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
@Override
public void onCameraMoveStarted(int i) {
if(GoogleMap.OnCameraMoveStartedListener.REASON_API_ANIMATION == i){
//do something
}
}
});
OnCircleClickListener’s onCircleClick method is called when a circle on the maps is clicked. You can add the listener to GoogleMap object by calling setOnCircleClickListener. In onCircleClick method, you can use Circle object, which is clicked, to change circle settings or other customizations on map.
gmap.setOnCircleClickListener(new GoogleMap.OnCircleClickListener() {
@Override
public void onCircleClick(Circle circle) {
circle.setFillColor(R.color.colorAccent);
}
});
OnInfoWindowClickListener’s onInfoWindowClick method is called when marker’s info window is clicked. You can add the listener to GoogleMap object by calling setOnInfoWindowClickListener. Method onInfoWindowClick is passed the Marker object to which info window anchored. Using the Marker object, you can customize marker or info window in the handler method.
gmap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
marker.hideInfoWindow();
}
});
OnInfoWindowCloseListener’s onInfoWindowClose method is called when info window is closed. You can add the listener to GoogleMap object by calling setOnInfoWindowCloseListener.
gmap.setOnInfoWindowCloseListener(new GoogleMap.OnInfoWindowCloseListener() {
@Override
public void onInfoWindowClose(Marker marker) {
marker.setIcon(BitmapDescriptorFactory.defaultMarker( BitmapDescriptorFactory.HUE_BLUE));
}
});
OnMarkerClickListener’s onMarkerClick method is called when a marker is clicked. You can add the listener to GoogleMap object by calling setOnMarkerClickListener. Return true to override the default behavior.
gmap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
return true;
}
});
OnPoiClickListener’s onPoiClick method is called when any point of interest on the map is clicked. You can add the listener to GoogleMap object by calling setOnPoiClickListener method. PointOfInterest object which is passed to onPoiClick method can be used to get information about point of interest and do something like adding marker to POI and moving camera to POI as shown in the below example.
gmap.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
@Override
public void onPoiClick(PointOfInterest pointOfInterest) {
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(pointOfInterest.latLng);
gmap.addMarker(markerOptions);
gmap.moveCamera(CameraUpdateFactory.newLatLng(pointOfInterest.latLng));
}
});
OnPolygonClickListener’s onPolygonClick method is called when a polygon is clicked. You can add the listener to GoogleMap object by calling setOnPolygonClickListener, using polygon object passed to the handler method, you can customize the map.
gmap.setOnPolygonClickListener(new GoogleMap.OnPolygonClickListener() {
@Override
public void onPolygonClick(Polygon polygon) {
polygon.setStrokeColor(Color.DKGRAY);
}
});
You can display Google map in lite mode in android apps by setting lite mode attribute to true in xml or programmatically. You can set zoom, add marker, info window and shapes and select one of the supported map types to map, but lite mode doesn’t support camera tilt and bearing. User viewing the lite map can’t zoom or pan.
To enable lite mode in xml layout, you need to set liteMode attribute to true.
<com.google.android.gms.maps.MapView
android:id="@+id/map_view"
. . .
app:liteMode="true"/>
To enable lite mode in code, you need to instantiate MapView passing GoogleMapOptions object to constructor and then add the MapView object to layout. GoogleMapOptions contains lite mode attribute which you need to set to true.
LinearLayout ll = findViewById(R.id.map_view_layout);
GoogleMapOptions options = new GoogleMapOptions().liteMode(true);
mapView = new MapView(this, options);
ll.addView(mapView);
mapView.onCreate(mapViewBundle);
mapView.getMapAsync(this);