Mapy v Xamarin.iOS
Mapy jsou běžnou funkcí ve všech moderních mobilních operačních systémech. iOS nabízí nativně podporu mapování prostřednictvím architektury Map Kit. Pomocí sady Map Kit můžou aplikace snadno přidávat bohaté interaktivní mapy. Tyto mapy lze přizpůsobit různými způsoby, například přidáním poznámek k označení umístění na mapě a překrytím grafiky libovolných obrazců. Map Kit má dokonce integrovanou podporu pro zobrazení aktuálního umístění zařízení.
Přidání mapy
Přidání mapy do aplikace se provádí přidáním MKMapView
instance do hierarchie zobrazení, jak je znázorněno níže:
// map is an MKMapView declared as a class variable
map = new MKMapView (UIScreen.MainScreen.Bounds);
View = map;
MKMapView
UIView
je podtřída, která zobrazuje mapu. Jednoduše přidáním mapy pomocí výše uvedeného kódu vznikne interaktivní mapa:
Styl mapy
MKMapView
podporuje 3 různé styly map. Pokud chcete použít styl mapy, jednoduše nastavte MapType
vlastnost na hodnotu z výčtu MKMapType
:
map.MapType = MKMapType.Standard; //road map
map.MapType = MKMapType.Satellite;
map.MapType = MKMapType.Hybrid;
Následující snímek obrazovky ukazuje různé dostupné styly mapy:
Posouvání a přiblížení
MKMapView
zahrnuje podporu pro funkce interaktivity mapování, jako jsou:
- Přiblížení gestem připnutí
- Posouvání pomocí gesta posouvání
Tyto funkce je možné povolit nebo zakázat jednoduchým nastavením ZoomEnabled
a ScrollEnabled
vlastnostmi MKMapView
instance, kde výchozí hodnota platí pro oba. Pokud chcete například zobrazit statickou mapu, jednoduše nastavte odpovídající vlastnosti na false:
map.ZoomEnabled = false;
map.ScrollEnabled = false;
Umístění uživatele
Kromě interakce MKMapView
uživatelů má také integrovanou podporu pro zobrazení polohy zařízení. Dělá to pomocí architektury Core Location . Než budete mít přístup k umístění uživatele, musíte uživatele vyzvat. Chcete-li to provést, vytvořte instanci CLLocationManager
a volání RequestWhenInUseAuthorization
.
CLLocationManager locationManager = new CLLocationManager();
locationManager.RequestWhenInUseAuthorization();
//locationManager.RequestAlwaysAuthorization(); //requests permission for access to location data while running in the background
Všimněte si, že při pokusu o volání RequestWhenInUseAuthorization
ve verzích iOS starších než 8.0 dojde k chybě. Před voláním nezapomeňte zkontrolovat verzi iOS, pokud máte v úmyslu podporovat verze starší než 8.
Přístup k umístění uživatele také vyžaduje úpravy souboru Info.plist. Měly by být nastaveny následující klíče týkající se údajů o poloze:
- NSLocationWhenInUseUsageDescription – Pokud při interakci s vaší aplikací přistupujete k umístění uživatele.
- NSLocationAlwaysUsageDescription – Pokud vaše aplikace přistupuje k umístění uživatele na pozadí.
Tyto klíče můžete přidat tak, že otevřete Soubor Info.plist a vyberete Zdroj v dolní části editoru.
Po aktualizaci souboru Info.plist a zobrazení výzvy uživateli, aby získal oprávnění pro přístup k jeho umístění, můžete zobrazit polohu uživatele na mapě nastavením ShowsUserLocation
vlastnosti na hodnotu true:
map.ShowsUserLocation = true;
Poznámky
MKMapView
podporuje také zobrazování obrázků, označovaných jako poznámky, na mapě. Můžou to být vlastní image nebo systémově definované špendlíky různých barev. Například následující snímek obrazovky ukazuje mapu s připnutím i vlastním obrázkem:
Přidání poznámky
Samotná poznámka má dvě části:
- Objekt
MKAnnotation
, který obsahuje data modelu o anotaci, například název a umístění poznámky. - ,
MKAnnotationView
který obsahuje obrázek, který se má zobrazit, a volitelně popisek, který se zobrazí, když uživatel klepne na poznámku.
Map Kit používá vzor delegování iOS k přidání poznámek do mapy, kde Delegate
vlastnost objektu MKMapView
je nastavena na instanci objektu MKMapViewDelegate
. Je to implementace tohoto delegáta, která je zodpovědná za vrácení poznámky MKAnnotationView
.
Pokud chcete přidat poznámku, nejprve se přidá poznámka voláním AddAnnotations
instance MKMapView
:
// add an annotation
map.AddAnnotations (new MKPointAnnotation (){
Title="MyAnnotation",
Coordinate = new CLLocationCoordinate2D (42.364260, -71.120824)
});
Když se na mapě zobrazí umístění poznámek, zavolá metoda delegátaGetViewForAnnotation
, MKMapView
aby se zobrazilaMKAnnotationView
.
Následující kód například vrátí systém 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;
}
Opakované přidávání poznámek
Chcete-li ušetřit paměť, MKMapView
umožňuje, aby bylo zobrazení poznámek ve fondu pro opakované použití, podobně jako jsou buňky tabulky opakovaně používány. Získání zobrazení poznámek z fondu se provádí voláním DequeueReusableAnnotation
:
MKAnnotationView pinView = (MKPinAnnotationView)mapView.DequeueReusableAnnotation (pId);
Zobrazení bublinových popisků
Jak už bylo zmíněno dříve, poznámka může volitelně zobrazit bublinový popisek. Chcete-li zobrazit bublinový popisek jednoduše nastaven CanShowCallout
na hodnotu true na kartě MKAnnotationView
. Výsledkem je zobrazení názvu poznámky při klepnutí na poznámku, jak je znázorněno na obrázku:
Přizpůsobení bublinového popisku
Popisek lze také přizpůsobit tak, aby zobrazoval zobrazení levého a pravého přístupového objektu, jak je znázorněno níže:
pinView.RightCalloutAccessoryView = UIButton.FromType (UIButtonType.DetailDisclosure);
pinView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile ("monkey.png"));
Výsledkem tohoto kódu je následující bublinový popisek:
Pokud chcete pracovat s uživatelem klepnutím na správné příslušenství, jednoduše implementujte metodu CalloutAccessoryControlTapped
v :MKMapViewDelegate
public override void CalloutAccessoryControlTapped (MKMapView mapView, MKAnnotationView view, UIControl control)
{
...
}
Překryvy
Další způsob, jak vrstvit grafiku na mapě, je použití překrytí. Překryvné vrstvy podporují grafický obsah výkresu, který se při přiblížení zvětšuje s mapou. iOS poskytuje podporu pro několik typů překryvů, mezi které patří:
- Mnohoúhelníky – běžně se používá ke zvýraznění určité oblasti na mapě.
- Křivky – často se zobrazuje při zobrazení trasy.
- Kruhy – slouží ke zvýraznění kruhové oblasti mapy.
Kromě toho je možné vytvořit vlastní překrytí, aby bylo možné zobrazit libovolné geometrie s podrobným přizpůsobeným kódem výkresu. Například meteorologický radar by byl vhodným kandidátem pro vlastní překryv.
Přidání překryvného objektu
Podobně jako poznámky zahrnuje přidání překrytí 2 části:
- Vytvoření objektu modelu pro překrytí a jeho přidání do objektu
MKMapView
. - Vytvoření zobrazení pro překryvné zobrazení v objektu
MKMapViewDelegate
.
Model pro překryvné vrstvy může být libovolná MKShape
podtřída. Xamarin.iOS obsahuje MKShape
podtřídy pro mnohoúhelníky, lomené čáry a kruhy prostřednictvím MKPolyline
MKPolygon
tříd a MKCircle
tříd.
Například následující kód se používá k přidání MKCircle
:
var circleOverlay = MKCircle.Circle (mapCenter, 1000);
map.AddOverlay (circleOverlay);
Zobrazení pro překryvné zobrazení je MKOverlayView
instance, která je vrácena GetViewForOverlay
v objektu MKMapViewDelegate
. Každá z nich MKShape
má odpovídající, MKOverlayView
která ví, jak zobrazit daný obrazec. Pro MKPolygon
tam je MKPolygonView
. Podobně odpovídá MKPolyline
MKPolylineView
, a pro MKCircle
tam je MKCircleView
.
Například následující kód vrátí MKCircleView
pro: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;
}
Zobrazí se kruh na mapě, jak je znázorněno:
Místní vyhledávání
iOS obsahuje rozhraní API pro místní vyhledávání se sadou Map Kit, které umožňuje asynchronní vyhledávání bodů zájmu v zadané geografické oblasti.
Pokud chcete provést místní vyhledávání, musí aplikace postupovat takto:
- Vytvořit
MKLocalSearchRequest
objekt. - Vytvořte objekt
MKLocalSearch
z objektuMKLocalSearchRequest
. - Zavolejte metodu
Start
objektuMKLocalSearch
. MKLocalSearchResponse
Načtěte objekt v zpětném volání.
Samotné rozhraní API místního vyhledávání neposkytuje žádné uživatelské rozhraní. Nevyžaduje ani použití mapy. Aby se ale místní vyhledávání prakticky využilo, musí aplikace poskytnout nějaký způsob, jak zadat vyhledávací dotaz a zobrazit výsledky. Vzhledem k tomu, že výsledky budou obsahovat údaje o poloze, často dávají smysl je zobrazit na mapě.
Přidání uživatelského rozhraní místního vyhledávání
Jedním zezpůsobůch UISearchBar
UISearchController
Následující kód přidá UISearchController
(který má vlastnost vyhledávacího pruhu) v ViewDidLoad
metodě 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;
Všimněte si, že zodpovídáte za začlenění objektu vyhledávacího panelu do uživatelského rozhraní. V tomto příkladu jsme ho přiřadili k ovládacímu prvku TitleView navigačního panelu, ale pokud ve své aplikaci nepoužíváte navigační kontroler, budete muset najít jiné místo, kde ho chcete zobrazit.
V tomto fragmentu kódu jsme vytvořili další vlastní kontroler zobrazení – searchResultsController
který zobrazuje výsledky hledání a pak jsme tento objekt použili k vytvoření objektu kontroleru vyhledávání. Vytvořili jsme také nový aktualizátor vyhledávání, který se aktivuje, když uživatel pracuje s panelem hledání. Přijímá oznámení o hledáních pomocí jednotlivých klávesových úhošť a zodpovídá za aktualizaci uživatelského rozhraní.
Podíváme se, jak implementovat jak tuto searchResultsController
verzi, tak i searchResultsUpdater
později v této příručce.
Výsledkem je panel hledání zobrazený na mapě, jak je znázorněno níže:
Zobrazení výsledků hledání
Abychom mohli zobrazit výsledky hledání, musíme vytvořit vlastní kontroler zobrazení; normálně a UITableViewController
. Jak je znázorněno výše, searchResultsController
předá se konstruktoru searchController
při jeho vytváření.
Následující kód je příkladem vytvoření tohoto vlastního kontroleru zobrazení:
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);
}
});
}
}
Aktualizace výsledků hledání
Jedná SearchResultsUpdater
se jako mediátor mezi searchController
vyhledávacím panelem a výsledky hledání.
V tomto příkladu musíme nejprve vytvořit vyhledávací metodu v souboru SearchResultsViewController
. K tomu musíme vytvořit MKLocalSearch
objekt a použít ho k vydání hledání , MKLocalSearchRequest
výsledky se načtou v zpětném volání předané Start
metodě objektu MKLocalSearch
. Výsledky se pak vrátí v objektu MKLocalSearchResponse
obsahujícím pole MKMapItem
objektů:
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);
}
});
}
Pak v naší MapViewController
vytvoříme vlastní implementaci UISearchResultsUpdating
, která je přiřazena k SearchResultsUpdater
vlastnosti našeho searchController
v části Přidání místního vyhledávacího uživatelského rozhraní :
public class SearchResultsUpdator : UISearchResultsUpdating
{
public event Action<string> UpdateSearchResults = delegate {};
public override void UpdateSearchResultsForSearchController (UISearchController searchController)
{
this.UpdateSearchResults (searchController.SearchBar.Text);
}
}
Výše uvedená implementace přidá do mapy poznámku, když je položka vybrána z výsledků, jak je znázorněno níže:
Důležité
UISearchController
byla implementována v iOSu 8. Pokud chcete zařízení podporovat dříve, budete muset použít UISearchDisplayController
.
Shrnutí
Tento článek prozkoumal architekturu mapových sad pro iOS. Nejprve se podívala na to, jak MKMapView
třída umožňuje zahrnutí interaktivních map do aplikace. Pak ukázal, jak dále přizpůsobit mapy pomocí poznámek a překryvných objektů. Nakonec prozkoumala možnosti místního vyhledávání, které byly přidány do mapové sady s iOSem 6.1, a ukázala, jak použít provádění dotazů založených na poloze pro body zájmu a přidat je do mapy.