Blog technique sur mes expériences de développeur.
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 :
L’intégralité de ce cours est disponible dans le CourseLab OpenClassrooms !
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
.
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;
}
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)
{
}
}
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 carteGoogleMap.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.
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.
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 :
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.
Je vais d’ailleurs privilégier l’utilisation de cette méthode dans la suite du tutoriel, mais il me paraissait important que vous connaissiez la méthode moveCamera
.
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.
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));
}
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 :
LatLng
afin de préciser les coordonnées GPS du point sur lequel on souhaite centrer la cartefloat
pour le zoomfloat
pour l’inclinaisonfloat
pour l’orientationVoici 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 :
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 :
zoom
tilt
bearing
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.
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
.
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);
}
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 :
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.
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 :
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);
}
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 :
Une nouvelle fois, les fonctionnalités que nous allons voir ici sont faites dans le cadre pédagogique. D’un point de vu expérience utilisateur, je vous déconseille de désactiver certaines gestures.
Dans le chapitre précédent, nous avions vu qu’il existe deux gestures permettant de zoomer ou dézoomer sur une carte :
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);
}
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);
}
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 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);
}
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);
}
A partir d’une instance d’objet GoogleMap
, il est possible de personnaliser grandement l’expérience d’utilisation de la carte et notamment :