Ludovic ROLAND

Blog technique sur mes expériences de développeur.

Intégrer et utiliser une carte google dans une application android (6/7) : Manipulations de base (2/2)

7 août 2016

Dans la chapitre précédent, nous avons vu qu’il était possible de manipuler et personnaliser notre carte Google à l’aide d’attributs XML directement dans le layout de notre fragment. Dans ce nouveau chapitre, nous allons donc apprendre à récupérer une référence vers notre carte afin de manipuler notre carte directement dans le code du fragment à l’aide du Java.

Dans ce chapitre, nous allons grosso-modo être iso-périmètre avec le chapitre précédent sauf que tout sera fait à l’aide du langage Java. Le programme est donc le suivant :

  • régler le niveau de zoom
  • changer la partie de la carte à afficher
  • animer la caméra
  • etc.

Plan

Récupérer une référence de la carte Google

Comme je vous le disais, toujours en introduction de ce chapitre, nous allons apprendre à manipuler et personnaliser notre carte, mais pour ce faire, il convient d’abord de récupérer une référence vers notre carte afin de pouvoir la manipuler dans notre MainActivityFragment.

Récupérer une référence du MapFragment

Pour récupérer une référence vers notre carte Google, nous allons être obligé de passer par le SupportMapFragment que nous avons utilisé dans le layout disponible quelques lignes plus haut. Il s’agit d’une opération assez basique si vous maitrisez déjà.

Dans la méthode onCreateView de notre MainActivityFragment, juste après l’inflation du layout, il convient donc d’utiliser la méthode findFragmentById du FragmentManager du Fragment :

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
  final View rootView = inflater.inflate(R.layout.fragment_main, container, false);
  final SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
  return rootView;
}

Récupérer une référence d’un objetGoogleMap

Maintenant que nous avons récupérer une référence de notre SupportMapFragment, nous allons être en mesure de récupérer une référence vers un objet GoogleMap, c’est-à-dire notre à proprement parler que nous allons pouvoir manipuler à volonté.

La récupération de l’objet GoogleMap, se fait à partir de notre instance de SupportMapFragment et plus précisément grâce à la méthode getMapAsync. Il s’agit d’une méthode asynchrone à laquelle il convient de passer une interface de type OnMapReadyCallback et qui nous permet de récupérer une référence à un objet GoogleMap lorsque notre carte est disponible à l’utilisation.

Nous pourrions très bien faire une implémentation inline de l’interface OnMapReadyCallback, mais, afin d’être le plus propre possible, nous allons demander à notre fragment d’implémenter l’interface. Votre IDE devrait alors vous demander d’implémenter la méthode OnMapReady. Cette méthode vous permet alors de récupérer une référence vers un objet GoogleMap à travers son seul paramètre.

Voici ce à quoi devrait alors ressembler votre fragment :

public final static class PlaceholderFragment
  extends Fragment
  implements OnMapReadyCallback
{

  public PlaceholderFragment()
  {
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
  {
    final View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    final MapFragment mapFragment = (MapFragment) getActivity().getFragmentManager().findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
    return rootView;
  }

  @Override
  public void onMapReady(GoogleMap googleMap)
  {
  }
}

Choisir le type de la carte

Dans le chapitre précédent, nous avions vu que grâce aux attributs XML du layout, il était possible de changer le type de la carte à afficher en choisissant par exemple une carte de type “satellite” ou “terrain”. Il est également possible de personnaliser le type de la carte directement en Java à l’aide de la méthode setMapType de la classe GoogleMap. Cette méthode accepte pour paramètres les constantes suivantes :

  • GoogleMap.MAP_TYPE_NONE pour n’afficher aucune carte
  • GoogleMap.MAP_TYPE_NORMAL pour afficher la carte par défaut.
  • GoogleMap.MAP_TYPE_SATELLITE pour afficher une carte de type satellite.
  • GoogleMap.MAP_TYPE_TERRAIN pour afficher une carte de type terrain.
  • GoogleMap.MAP_TYPE_HYBRID pour afficher une carte hybride.

Par exemple, si vous choisissez la constante GoogleMap.MAP_TYPE_SATELLITE, votre méthode onMapReady devrait ressembler à ça :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
}

Une nouvelle fois, je vous laisse le soin de tester les différentes constantes pour voir le résultat produit.

Manipuler la caméra et la position initiale de la carte

Comme nous l’avions vu dans le chapitre précédent, je vous propose de jouer avec la caméra de notre carte Google afin de pouvoir modifier sa position, son inclinaison, son orientation, etc.

Changer la position de la caméra sur la carte

Comme nous l’avions vu avec les attributs XML, je vous propose de débuter par le changement de la position de la caméra sur la carte. Une nouvelle fois, je vous propose de centrer la carte sur Paris dont les coordonnées GPS n’ont à prori pas changé depuis le chapitre précédent :

  • Latitude : 48.8534100
  • Longitude : 2.3488000

Ce changement de position peut se faire via la méthode moveCamera de la classe GoogleMap. Cette méthode accepte un seul paramètre qui est de type CameraUpdate. Un objet CameraUpdate se construit à l’aide des méthodes statiques de la classe CameraUpdateFactory. Aussi, puisque dans le cadre de ce tutoriel nous ne souhaitons changer que la latitude et la longitude, nous pouvons utiliser la méthode statique newLatLng qui accepte justement un objet de type LatLng, qui via son constructeur nous permet de définir une latitude et une longitude.

Bien que le paragraphe précédent paraisse compliqué, une seule ligne de code est nécessaire pour passer du français au Java :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(48.8534100, 2.3488000)));
}

Nous pouvons exécuter l’application dès maintenant pour vérifier le bon fonctionnement de notre code :

Comme c’était déjà le cas lorsque nous utilisions les attributs XML, c’est bien la France qui est au centre de la carte.

Vous l’avez peut-être remarqué, le déplacement de la carte de la position originale vers Paris est assez brute. Il est possible d’obtenir un résultat beaucoup plus sympa en utilisant la méthode animateCamera plutôt que la méthode moveCamera. Comme son nom le laisse deviner, le changement de position va s’accompagner d’une petite animation qui permet à votre application de gagner en expérience utilisateur.

Comme dans le chapitre précédent, pour vérifier que c’est bien Paris qui est au centre de la carte et non une autre ville de France, je vous propose de voir immédiatement comment modifier le niveau de de zoom de la carte.

Changer le niveau de zoom

Pour modifier le niveau de zoom de la carte, nous allons donc utiliser la méthode animateCamera à laquelle nous allons une nouvelle fois passer un paramètre de type CameraUpdate que nous allons construire à l’aide des méthodes statiques de la classe CameraUpdateFactory. La différence avec le paragraphe précédent c’est que ce coup-ci, nous n’allons pas utiliser la méthode newLatLng mais la méthode newLatLngZoom. Cette nouvelle méthode accepte deux paramètres : un objet de type LatLng ainsi qu’un nombre float pour le zoom.

Une nouvelle fois, le passage du français au Java tient sur une ligne :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(48.8534100, 2.3488000), 10));
}

Exécutez notre application pour vérifier que le niveau de zoom a bien changé. Vous aurez très certainement repéré l’animartion qui accompagne le déplacement de la carte et le zoom sur Paris :

A noter que si vous aviez voulu régler uniquement le niveau de zoom sans changer le point sur lequel la carte est centrée, vous auriez pu utiliser la méthode statique zoomTo de la classe CameraUpdateFactory :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.animateCamera(CameraUpdateFactory.zoomTo(10));
}

Changer l’orientation et l’inclinaison de la carte

Si dans le chapitre précédent nous avions comment il était possible de changer l’orientation et l’inclinaison de la carte grâce à deux attributs XML différents, nous allons voir qu’en Java il est possible de tout manipuler à l’aide d’une seule méthode.

Modifier l’orientation, l’inclinaison, le zoom, la latitude et la longitude d’un carte se fait toujours à l’aide de la méthode animateCamera de la classe GoogleMap à laquelle nous allons une nouvelle fois passer un paramètre de type CameraUpdate que nous allons encore une fois construire à l’aide des méthodes statiques de la classe CameraUpdateFactory. Cette fois-ci, nous allons utiliser la méthode newCameraPosition qui accepte une seul paramètre : un objet de type CameraPosition. Il est possible d’en construire un grâce au constructeur de l’objet. Ce dernier accepte quatre paramètres :

  • un objet de type LatLng afin de préciser les coordonnées GPS du point sur lequel on souhaite centrer la carte
  • un nombre float pour le zoom
  • un nombre float pour l’inclinaison
  • un nombre float pour l’orientation

Voici ce que vous devriez avoir une fois traduit en Java :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(new LatLng(49.145135, 2.675194), 16, 45, 225)));
}

Si vous lancez l’application, vous devriez alors avoir la carte suivante sur l’écran de votre téléphone ou tableau :

Récupérer les différentes valeurs de la carte

Jusqu’à maintenant, nous n’avons que modifier les valeurs de latitude, longitude, zoom, etc de la carte. Il peut également être très intéressant de récupérer ces valeurs afin de les exploiter ou tout simplement vérifier la position de la carte.

La récupération de toutes les valeurs que nous venons de voir se fait à travers la méthode getCameraPosition de la classe GoogleMap qui nous renvoie un objet de type CameraPosition. Il est ensuite possible de récupérer les différentes valeurs voulues via les différents attributs de l’objet à savoir :

  • le zoom via l’attribut zoom
  • l’inclinaison via l’attribut tilt
  • la rotation via l’attribut bearing
  • la longitude et la latitude via l’attribut target

A noter que cet attribut target est en réalité un objet de type LatLong. Aussi, pour récupérer la longitude et la latitude, il convient d’utiliser les attributs du même nom.

Pour vérifier que tous ces attributs nous renvoient bien les valeurs espérées, je vous propose de placer quelques lignes de debug dans la méthode onMapReady de votre fragment :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(new LatLng(49.145135, 2.675194), 16, 45, 225)));

  Log.d("onMapReady", "zoom : '" + googleMap.getCameraPosition().zoom + "'");
  Log.d("onMapReady", "bearing : '" + googleMap.getCameraPosition().bearing + "'");
  Log.d("onMapReady", "tilt : '" + googleMap.getCameraPosition().tilt + "'");
  Log.d("onMapReady", "longitude : '" + googleMap.getCameraPosition().target.longitude + "'");
  Log.d("onMapReady", "latitude : '" + googleMap.getCameraPosition().target.latitude + "'");
}

Après l’exécution de l’application, vous devriez retrouver les lignes suivantes dans le logcat de votre IDE :

03-30 22:49:45.643 2998-2998/fr.openclassrooms.geolocalisation D/onMapReady﹕ zoom : '16.0'
03-30 22:49:45.643 2998-2998/fr.openclassrooms.geolocalisation D/onMapReady﹕ bearing : '225.0'
03-30 22:49:45.643 2998-2998/fr.openclassrooms.geolocalisation D/onMapReady﹕ tilt : '45.0'
03-30 22:49:45.643 2998-2998/fr.openclassrooms.geolocalisation D/onMapReady﹕ longitude : '2.6751940324902534'
03-30 22:49:45.643 2998-2998/fr.openclassrooms.geolocalisation D/onMapReady﹕ latitude : '49.145135094932634'

Le résultat semble bien être celui attendu puisque l’ensemble des valeurs est cohérent avec celle que nous avions donné à notre carte.

Personnaliser l’affichage des contrôles

Comme c’était le cas dans le chapitre précédent, le changement d’orientation et d’inclinaison de la carte a automatiquement fait apparaître une petite boussole en haut à gauche de notre carte. Tout comme c’était le cas pour les attributs XML, il est possible de personnaliser l’affichage des contrôles à l’aide du Java.

L’ensemble des personnalisations que nous allons voir maintenant sont possibles grâce aux méthodes de la classe UiSettings. Pour récupérer une instance de cette classe, il convient d’appeler la méthode getUiSettings sur une instance de classe GoogleMap.

Affichage de la boussole

Pour rappel, le comportement par défaut de la carte veut que la boussole s’affiche automatiquement lorsque l’inclinaison ou l’orientation de la carte est modifiée. Ce comportement par défaut est donc personnalisable via la méthode setCompassEnabled de la classe UiSettings. Cette méthode accepte un seul paramètre qui est un booléen. Aussi, il convient de renseigner la valeur true pour conserver le comportement par défaut et false si l’on souhaite cacher la boussole même si l’inclinaison ou l’orientation de la carte sont changées.

Dans le cadre de notre exemple, je vous propose donc de cacher la boussole malgré la modification de l’orientation de la carte :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setCompassEnabled(true);
}

Affichage des contrôles de zoom

Comme c’était le cas au moment de travailler avec les attributs XML dans le chapitre précédent, si les utilisateurs veulent zoomer ou dézoomer sur un point de la carte, la seule possibilité qu’ils ont c’est de connaître et utiliser la gesture dîte de pinch to zoom ou encore taper deux fois sur l’écran. Grâce à la méthode setZoomControlsEnabled de la classe UiSettings, il est possible d’afficher des contrôles de zoom sur la carte. Pour rappel, ces contrôles se traduisent par :

  • un bouton “+” permettant de zoomer.
  • un bouton “-“ permettant de dézoomer.

Tout comme la méthode permettant d’afficher la boussole, la méthode setZoomControlsEnabled accepte un seul paramètre de type booléen. Il convient donc de renseigner la valeur true pour afficher les contrôles de zoom et false pour les cacher (il s’agit de la valeur par défaut).

Dans le cadre de notre exemple, nous allons donc forcer l’affichage des contrôles de zoom :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setZoomControlsEnabled(true);
}

Comme vous pouvez le constater dans la capture d’écran ci-dessous, deux boutons, permettant de zoomer et dézoomer, sont apparus en bas à droite de l’écran.

Affichage d’une MapToolbar

Depuis peu de temps, à la sélection d’un marker , c’est-à-dire une punaise, sur la carte, une MapToolbar s’affiche par défaut proposant deux actions supplémentaires à l’utilisateur :

  • ouvrir la carte dans l’application native Google Maps
  • trouver un itinéraire vers le marker dans l’application native Google Maps

Cette toolbar est désactivable grâce à la méthode setMapToolbarEnabled de la classe UiSettings. Comme pour les précédentes méthodes que nous avons vu dernièrement, elle accepte un seul paramètre de type booléen. Il convient donc de renseigner la valeur true pour autoriser l’affichage de la MapToolbar (il s’agit du comportement par défaut) et false pour ne pas autoriser son affichage.

Dans le cadre de notre exemple, nous allons autoriser son affichage :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setMapToolbarEnabled(true);
}

Personnaliser les gestures autorisées

Comme pour le chapitre précédent, je vous propose de terminer celui-ci avec les gestures. Pour rappel, les gestures sont l’ensemble des gestes qui permettent via un positionnement précis des doigts sur l’écran du terminal d’effectuer un certaines actions comme par exemple :

  • zoomer sur la carte
  • dézoomer sur la carte
  • tourner la carte
  • etc.

Les gestures de zoom et dézoom

Dans le chapitre précédent, nous avions vu qu’il existe deux gestures permettant de zoomer ou dézoomer sur une carte :

  • taper deux fois sur l’écran
  • le pinch to zoom

Tout comme il est possible d’activer ou désactiver ces gestures grâce à un attribut XML, nous allons voir qu’il est également possible de le faire côté Java. Pour ce faire, il convient d’utiliser la méthode setZoomGesturesEnabled de la classe UiSettings. Cette méthode accepte un seul paramètre qui est un booléen. Aussi, la valeur true permet d’activer les gestures (il s’agit du comportement par défaut), tandis que la valeur false permet de les désactiver.

Dans le cadre de notre exemple, nous allons désactiver ces gestures :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setZoomGesturesEnabled(false);
}

La gesture de déplacement

Poiur activer ou désactiver la gesture de déplacement, également appelée gesture de scroll, il convient d’utiliser la méthode setScrollGesturesEnabled de la classe UiSettings. Comme la plupart des méthodes que nous avons vu dernièrement, la méthode setScrollGesturesEnabled accepte un seul paramètre de type booléen. Aussi, la valeur true permet d’activer la gesture (il s’agit de la valeur par défaut) et la valeur false permet de la désactiver.

Dans le cadre de ce tutoriel, je vous propose de désactiver la gesture de scroll :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setScrollGesturesEnabled(false);
}

La gesture de rotation

Souvenez vous, dans le chapitre précédent, nous avions vu que l’utilisateur avait la possibilité de changer l’orientation de la carte en se servant de ses doigts comme d’un compas. Cette gesture de rotation est activable ou désactivable grâce à la méthode setRotateGesturesEnabled de la classe UiSettings. Encore une fois, il s’agit d’une méthode acceptant un seul paramètre de type booléen : la valeur true permettant d’activer la possibilité de changer l’orientation de la carte (il s’agit de la valeur par défaut) et la valeur false permetta de bloquer la carte sur une orientation déterminée.

Voici ce à quoi ressemble le layout dans le cas où la gesture est désactivée :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setRotateGesturesEnabled(false);
}

La gesture d’inclinaison

La dernière gesture que nous avions vu dans le chapitre précédent est une gesture permettant de changer l’inclinaison de la carte à l’aide de deux doigts. Une nouvelle fois, il existe une méthode Java permettant d’activer ou désactiver cette possibilité offerte à l’utilisateur. Il s’agit de la méthode setTiltGesturesEnabled de la classe UiSettings. Cette méthode accepte un seul paramètre de type booléen. Aussi, la valeur true permet d’activer la gesture (il s’agit de la valeur par défaut) tandis que la valeur false afin de la désactiver.

Dans le cadre de ce tutoriel, je vous propose de la désactiver :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setTiltGesturesEnabled(false);
}

Activer ou désactiver toute les gestures

Pour conclure ce chapitre, j’aimerais vous présenter une dernière méthode. Il s’agit de la méthode setAllGesturesEnabled de la classe UiSettings. Cette méthode, qui accepte un booléen en tant que seul paramètre, permet d’activer ou désactiver toutes les gestures que nous avons vu jusqu’à maintenant en une seule ligne de code. La valeur true permet d’activer toutes les gestures (il s’agit de la valeur par défaut) alors que la valeur false permet de toutes les désactiver.

Voici ce à quoi ressemblerait votre code si vous décidiez de désactiver toutes les gestures :

@Override
public void onMapReady(GoogleMap googleMap)
{
  googleMap.getUiSettings().setAllGesturesEnabled(false);
}

En résumé

A partir d’une instance d’objet GoogleMap, il est possible de personnaliser grandement l’expérience d’utilisation de la carte et notamment :

  • le type de la carte
  • la position et le niveau de zoom de la carte
  • l’affichage des contrôles
  • l’activation et la désactivation des gestures

Commentaires