Cartes dans Xamarin.iOS
Les cartes sont une fonctionnalité courante dans tous les systèmes d’exploitation mobiles modernes. iOS offre la prise en charge du mappage en mode natif via l’infrastructure map Kit. Avec Map Kit, les applications peuvent facilement ajouter des cartes riches et interactives. Ces cartes peuvent être personnalisées de différentes manières, telles que l’ajout d’annotations pour marquer des emplacements sur une carte et la superposition de graphiques de formes arbitraires. Map Kit a même une prise en charge intégrée pour afficher l’emplacement actuel d’un appareil.
Ajout d’une carte
L’ajout d’une carte à une application s’effectue en ajoutant une MKMapView
instance à la hiérarchie d’affichage, comme indiqué ci-dessous :
// map is an MKMapView declared as a class variable
map = new MKMapView (UIScreen.MainScreen.Bounds);
View = map;
MKMapView
est une UIView
sous-classe qui affiche une carte. L’ajout de la carte à l’aide du code ci-dessus produit une carte interactive :
Style de carte
MKMapView
prend en charge 3 styles différents de cartes. Pour appliquer un style de carte, définissez simplement la MapType
propriété sur une valeur de l’énumération MKMapType
:
map.MapType = MKMapType.Standard; //road map
map.MapType = MKMapType.Satellite;
map.MapType = MKMapType.Hybrid;
La capture d’écran suivante montre les différents styles de carte disponibles :
Mouvement panoramique et zoom
MKMapView
inclut la prise en charge des fonctionnalités d’interactivité de carte, telles que :
- Zoom via un mouvement de pincement
- Mouvement panoramique via un mouvement panoramique
Ces fonctionnalités peuvent être activées ou désactivées en définissant simplement les propriétés et ScrollEnabled
les ZoomEnabled
propriétés de l’instanceMKMapView
, où la valeur par défaut est true pour les deux. Par exemple, pour afficher une carte statique, définissez simplement les propriétés appropriées sur false :
map.ZoomEnabled = false;
map.ScrollEnabled = false;
Emplacement de l'utilisateur
Outre l’interaction utilisateur, MKMapView
elle prend également en charge l’affichage de l’emplacement de l’appareil. Il effectue cette opération à l’aide de l’infrastructure d’emplacement principal. Avant de pouvoir accéder à l’emplacement de l’utilisateur, vous devez inviter l’utilisateur. Pour ce faire, créez une instance de CLLocationManager
et appelez RequestWhenInUseAuthorization
.
CLLocationManager locationManager = new CLLocationManager();
locationManager.RequestWhenInUseAuthorization();
//locationManager.RequestAlwaysAuthorization(); //requests permission for access to location data while running in the background
Notez que dans les versions d’iOS antérieures à la version 8.0, la tentative d’appel RequestWhenInUseAuthorization
entraîne une erreur. Veillez à vérifier la version d’iOS avant d’effectuer cet appel si vous envisagez de prendre en charge les versions antérieures à 8.
L’accès à l’emplacement de l’utilisateur nécessite également des modifications apportées à Info.plist. Vous devez définir les clés suivantes relatives aux données d’emplacement :
- NSLocationWhenInUseUsageDescription : cette clé est utilisée quand vous accédez à l’emplacement d’un utilisateur en train d’interagir avec votre application.
- NSLocationAlwaysUsageDescription : cette clé est utilisée quand votre application accède à l’emplacement d’un utilisateur en arrière-plan.
Vous pouvez ajouter ces clés en ouvrant Info.plist et en sélectionnant Source en bas de l’éditeur.
Une fois que vous avez mis à jour Info.plist et invité l’utilisateur à accéder à son emplacement, vous pouvez afficher l’emplacement de l’utilisateur sur la carte en définissant la ShowsUserLocation
propriété sur true :
map.ShowsUserLocation = true;
Annotations
MKMapView
prend également en charge l’affichage d’images, appelées annotations, sur une carte. Il peut s’agir d’images personnalisées ou de broches définies par le système de différentes couleurs. Par exemple, la capture d’écran suivante montre une carte avec une épingle et une image personnalisée :
Ajout d’une annotation
Une annotation elle-même comporte deux parties :
- Objet
MKAnnotation
, qui inclut des données de modèle sur l’annotation, telles que le titre et l’emplacement de l’annotation. MKAnnotationView
Qui contient l’image à afficher et éventuellement une légende affichée lorsque l’utilisateur appuie sur l’annotation.
Map Kit utilise le modèle de délégation iOS pour ajouter des annotations à une carte, où la Delegate
propriété du MKMapView
kit est définie sur une instance d’un MKMapViewDelegate
. Il s’agit de l’implémentation de ce délégué responsable du renvoi MKAnnotationView
d’une annotation.
Pour ajouter une annotation, l’annotation est d’abord ajoutée en appelant AddAnnotations
l’instance MKMapView
:
// add an annotation
map.AddAnnotations (new MKPointAnnotation (){
Title="MyAnnotation",
Coordinate = new CLLocationCoordinate2D (42.364260, -71.120824)
});
Lorsque l’emplacement de l’annotation devient visible sur la carte, il MKMapView
appelle la méthode de GetViewForAnnotation
son délégué pour obtenir l’affichage MKAnnotationView
.
Par exemple, le code suivant retourne un système fourni MKPinAnnotationView
:
string pId = "PinAnnotation";
public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
{
if (annotation is MKUserLocation)
return null;
// create pin annotation view
MKAnnotationView pinView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation (pId);
if (pinView == null)
pinView = new MKPinAnnotationView (annotation, pId);
((MKPinAnnotationView)pinView).PinColor = MKPinAnnotationColor.Red;
pinView.CanShowCallout = true;
return pinView;
}
Réutilisation des annotations
Pour économiser de la mémoire, MKMapView
permet de regrouper les vues d’annotations à des fins de réutilisation, comme la façon dont les cellules du tableau sont réutilisées. L’obtention d’une vue d’annotation à partir du pool est effectuée avec un appel à DequeueReusableAnnotation
:
MKAnnotationView pinView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation (pId);
Affichage des légendes
Comme mentionné précédemment, une annotation peut éventuellement afficher une légende. Pour afficher une légende simplement définie CanShowCallout
sur true sur le MKAnnotationView
. Cela entraîne l’affichage du titre de l’annotation lorsque l’annotation est tapée, comme indiqué :
Personnalisation de la légende
La légende peut également être personnalisée pour afficher les vues d’accessoires gauche et droite, comme indiqué ci-dessous :
pinView.RightCalloutAccessoryView = UIButton.FromType (UIButtonType.DetailDisclosure);
pinView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile ("monkey.png"));
Ce code entraîne la légende suivante :
Pour gérer l’utilisateur en appuyant sur l’accessoire approprié, implémentez simplement la CalloutAccessoryControlTapped
méthode dans :MKMapViewDelegate
public override void CalloutAccessoryControlTapped (MKMapView mapView, MKAnnotationView view, UIControl control)
{
...
}
Superpositions
Une autre façon de calquer des graphiques sur une carte consiste à utiliser des superpositions. Les superpositions prennent en charge le tracé de contenu graphique qui s’ajuste à la carte quand celle-ci est zoomée. iOS prend en charge plusieurs types de superpositions, notamment :
- Polygones : couramment utilisés pour mettre en surbrillance une région sur une carte.
- Polylines - Souvent vu lors de l’affichage d’un itinéraire.
- Cercles : utilisé pour mettre en surbrillance une zone circulaire d’une carte.
En outre, des superpositions personnalisées peuvent être créées pour afficher des géométries arbitraires avec du code de dessin précis et personnalisé. Par exemple, le radar météorologique serait un bon candidat pour une superposition personnalisée.
Ajout d’une superposition
Comme pour les annotations, l’ajout d’une superposition implique 2 parties :
- Création d’un objet de modèle pour la superposition et l’ajout à l’objet
MKMapView
. - Création d’une vue pour la superposition dans le
MKMapViewDelegate
.
Le modèle de la superposition peut être n’importe quelle MKShape
sous-classe. Xamarin.iOS inclut MKShape
des sous-classes pour les polygones, les polylignes et les cercles, via les classes et MKCircle
les MKPolygon
MKPolyline
classes respectivement.
Par exemple, le code suivant est utilisé pour ajouter un MKCircle
:
var circleOverlay = MKCircle.Circle (mapCenter, 1000);
map.AddOverlay (circleOverlay);
La vue d’une superposition est une MKOverlayView
instance retournée par le GetViewForOverlay
MKMapViewDelegate
fichier . Chacun MKShape
a un correspondant MKOverlayView
qui sait comment afficher la forme donnée. Pour MKPolygon
qu’il y ait MKPolygonView
. De même, MKPolyline
correspond à MKPolylineView
, et pour MKCircle
il y a MKCircleView
.
Par exemple, le code suivant retourne un MKCircleView
pour un MKCircle
:
public override MKOverlayView GetViewForOverlay (MKMapView mapView, NSObject overlay)
{
var circleOverlay = overlay as MKCircle;
var circleView = new MKCircleView (circleOverlay);
circleView.FillColor = UIColor.Blue;
return circleView;
}
Cela affiche un cercle sur la carte, comme indiqué :
Recherche locale
iOS inclut une API de recherche locale avec Map Kit, qui permet de rechercher des points d’intérêt asynchrones dans une région géographique spécifiée.
Pour effectuer une recherche locale, une application doit suivre les étapes suivantes :
- Créez l'objet
MKLocalSearchRequest
. - Créez un
MKLocalSearch
objet à partir duMKLocalSearchRequest
. - Appelez la
Start
méthode sur l’objetMKLocalSearch
. - Récupérez l’objet
MKLocalSearchResponse
dans un rappel.
L’API de recherche locale elle-même ne fournit aucune interface utilisateur. Il ne nécessite même pas d’utilisation d’une carte. Toutefois, pour utiliser la recherche locale, une application doit fournir un moyen de spécifier une requête de recherche et d’afficher les résultats. En outre, étant donné que les résultats contiennent des données d’emplacement, il est souvent judicieux de les afficher sur une carte.
Ajout d’une interface utilisateur de recherche locale
Une façon d’accepter l’entrée de recherche est avec un UISearchBar
, fourni par un UISearchController
et affiche les résultats dans une table.
Le code suivant ajoute le UISearchController
(qui a une propriété de barre de recherche) dans la ViewDidLoad
méthode de MapViewController
:
//Creates an instance of a custom View Controller that holds the results
var searchResultsController = new SearchResultsViewController (map);
//Creates a search controller updater
var searchUpdater = new SearchResultsUpdator ();
searchUpdater.UpdateSearchResults += searchResultsController.Search;
//add the search controller
searchController = new UISearchController (searchResultsController) {
SearchResultsUpdater = searchUpdater
};
//format the search bar
searchController.SearchBar.SizeToFit ();
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
searchController.SearchBar.Placeholder = "Enter a search query";
//the search bar is contained in the navigation bar, so it should be visible
searchController.HidesNavigationBarDuringPresentation = false;
//Ensure the searchResultsController is presented in the current View Controller
DefinesPresentationContext = true;
//Set the search bar in the navigation bar
NavigationItem.TitleView = searchController.SearchBar;
Notez que vous êtes responsable de l’incorporation de l’objet de barre de recherche dans l’interface utilisateur. Dans cet exemple, nous l’avons affecté à titleView de la barre de navigation, mais si vous n’utilisez pas de contrôleur de navigation dans votre application, vous devrez trouver un autre emplacement pour l’afficher.
Dans cet extrait de code, nous avons créé un autre contrôleur d’affichage personnalisé , searchResultsController
qui affiche les résultats de la recherche, puis nous avons utilisé cet objet pour créer notre objet de contrôleur de recherche. Nous avons également créé un nouveau générateur de mise à jour de recherche, qui devient actif lorsque l’utilisateur interagit avec la barre de recherche. Il reçoit des notifications sur les recherches avec chaque séquence de touches et est responsable de la mise à jour de l’interface utilisateur.
Nous allons examiner comment implémenter les searchResultsController
deux et les searchResultsUpdater
versions ultérieures de ce guide.
Cela entraîne l’affichage d’une barre de recherche sur la carte, comme indiqué ci-dessous :
Affichage des résultats de la recherche
Pour afficher les résultats de la recherche, nous devons créer un contrôleur de vue personnalisé ; normalement un UITableViewController
. Comme indiqué ci-dessus, il searchResultsController
est passé au constructeur du moment où searchController
il est créé.
Le code suivant est un exemple de création de ce contrôleur d’affichage personnalisé :
public class SearchResultsViewController : UITableViewController
{
static readonly string mapItemCellId = "mapItemCellId";
MKMapView map;
public List<MKMapItem> MapItems { get; set; }
public SearchResultsViewController (MKMapView map)
{
this.map = map;
MapItems = new List<MKMapItem> ();
}
public override nint RowsInSection (UITableView tableView, nint section)
{
return MapItems.Count;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (mapItemCellId);
if (cell == null)
cell = new UITableViewCell ();
cell.TextLabel.Text = MapItems [indexPath.Row].Name;
return cell;
}
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
// add item to map
CLLocationCoordinate2D coord = MapItems [indexPath.Row].Placemark.Location.Coordinate;
map.AddAnnotations (new MKPointAnnotation () {
Title = MapItems [indexPath.Row].Name,
Coordinate = coord
});
map.SetCenterCoordinate (coord, true);
DismissViewController (false, null);
}
public void Search (string forSearchString)
{
// create search request
var searchRequest = new MKLocalSearchRequest ();
searchRequest.NaturalLanguageQuery = forSearchString;
searchRequest.Region = new MKCoordinateRegion (map.UserLocation.Coordinate, new MKCoordinateSpan (0.25, 0.25));
// perform search
var localSearch = new MKLocalSearch (searchRequest);
localSearch.Start (delegate (MKLocalSearchResponse response, NSError error) {
if (response != null && error == null) {
this.MapItems = response.MapItems.ToList ();
this.TableView.ReloadData ();
} else {
Console.WriteLine ("local search error: {0}", error);
}
});
}
}
Mise à jour des résultats de la recherche
Il SearchResultsUpdater
agit en tant que médiateur entre la searchController
barre de recherche et les résultats de recherche.
Dans cet exemple, nous devons d’abord créer la méthode de recherche dans le SearchResultsViewController
. Pour ce faire, nous devons créer un MKLocalSearch
objet et l’utiliser pour émettre une recherche d’un MKLocalSearchRequest
, les résultats sont récupérés dans un rappel passé à la Start
méthode de l’objet MKLocalSearch
. Les résultats sont ensuite retournés dans un MKLocalSearchResponse
objet contenant un tableau d’objets MKMapItem
:
public void Search (string forSearchString)
{
// create search request
var searchRequest = new MKLocalSearchRequest ();
searchRequest.NaturalLanguageQuery = forSearchString;
searchRequest.Region = new MKCoordinateRegion (map.UserLocation.Coordinate, new MKCoordinateSpan (0.25, 0.25));
// perform search
var localSearch = new MKLocalSearch (searchRequest);
localSearch.Start (delegate (MKLocalSearchResponse response, NSError error) {
if (response != null && error == null) {
this.MapItems = response.MapItems.ToList ();
this.TableView.ReloadData ();
} else {
Console.WriteLine ("local search error: {0}", error);
}
});
}
Ensuite, dans notre article MapViewController
, nous allons créer une implémentation personnalisée de UISearchResultsUpdating
, qui est affectée à la SearchResultsUpdater
propriété de notre searchController
dans la section Ajout d’une interface utilisateur de recherche locale :
public class SearchResultsUpdator : UISearchResultsUpdating
{
public event Action<string> UpdateSearchResults = delegate {};
public override void UpdateSearchResultsForSearchController (UISearchController searchController)
{
this.UpdateSearchResults (searchController.SearchBar.Text);
}
}
L’implémentation ci-dessus ajoute une annotation à la carte lorsqu’un élément est sélectionné dans les résultats, comme indiqué ci-dessous :
Important
UISearchController
a été implémenté dans iOS 8. Si vous souhaitez prendre en charge les appareils antérieurs à celui-ci, vous devez utiliser UISearchDisplayController
.
Résumé
Cet article a examiné l’infrastructure map Kit pour iOS. Tout d’abord, il a examiné la façon dont la MKMapView
classe permet l’inclusion de cartes interactives dans une application. Il a ensuite montré comment personnaliser davantage les cartes à l’aide d’annotations et de superpositions. Enfin, elle a examiné les fonctionnalités de recherche locales qui ont été ajoutées au Kit de mappage avec iOS 6.1, montrant comment utiliser des requêtes basées sur des emplacements pour des points d’intérêt et les ajouter à une carte.