Tento článek byl vydán v rámci Xamarin UI July od Stevena Thewissena.
Při výběru tématu pro Xamarin UI July jsem zamíříl k nápadu který jsem měl již delší dobu v plánu napsat - zvýrazňování zemí na mapě v Xamarin.Forms. Tato funkčnost se může hodit, když uživateli naší aplikace zobrazujeme data filtrovaná dle země, či když uživatel vybírá svou zemi při vytváření svého účtu. Díky vizuální zpětné vazbě na mapě naše aplikace v obou případech ožije.
Zisk dat
Oblast každé země na mapě světa můžeme popsat pomocí jednoho či více víceúhelníků (v případě ostrovních zemí jako je Japonsko). Musíme najít datový zdroj, který nám poskytne přibližné hranice těchto oblastí, abychom je mohli zobrazit na mapě. Navíc chceme najít takový datový formát, který bude snadné parsovat v Xamarin aplikaci. Je velmi pravděpodobné, že jste se již setkali s formátem JSON, který je dnes de-facto standardem pro serializaci dat v mobilních aplikacích a webových API. Existuje však i varianta JSONu, která je specificky navržená pro ukládání geografických dat - GeoJSON. Ačkoliv je tento formát plně kompatbiliní s JSONem a mohli bychom jej jistě číst jen s použitím knihovny JSON.NET, existuje také skvělá open-source knihovna, díky které je práce s tímto formátem ještě jednodušší - GeoJSON.Net. S vybraným formátem už nám stačí jen najít správný zdroj dat. Naštěstí, open-source nás zachrání i zde! Tento GitHub repozitář obsahuje kompaktní (251 KB) GeoJSON soubor s přibližnými geometriemi všech zemí.
Perfektní, je čas začít programovat!
Uživatelské rozhraní
Nejprve si připravíme jednoduché uživatelské rozhraní na kterém budeme schopni zvýraznění zemí testovat:
Nejde o nic komplexního - pouze jednoduchý seznam zemí a mapa pod ním. Mapový ovladací prvek lze do projektu přidat postupem dle dokumentace. Pozor, že Map
už není součástí Xamarin.Forms a je dodávána separátně v balíčku Xamarin.Forms.Maps. V našem případě však použijeme vlastní variantu HighligtableMap
, kterou implementujeme později.
Podpora zvýrazňování na mapě
Výchozí Xamarin.Forms mapa nepodporuje vykreslování mnohoúhelníků nad mapou. To však rozhodně budeme potřebovat a musíme tedy napsat vlastní implementaci. Nejprve vytvoříme nekolik podpůrných tříd pro popis polygonu a zvýrazenění na mapě:
Všimněme si, že třída MapHighlight
podporuje více než jeden mnohoúhelník, což požadujeme pro některé země (viz. výše). Pro přidání možnosti zvýraznění potřebujeme implementovat vlastní variantu mapové komponenty:
Renderery mapy
UWP
Začneme implementaci platformních rendererů mapy s UWP. Ve chvíli, kdy aktualizujeme vlastnost Highlight
, odstraníme existující MapElements
z nativního mapového ovladacího prvku a přidáme mnohoúhelníky z aktuální instance MapHighlight
.
Android
Implementace rendereru v Androidu je přímočará a velmi podobná UWP. Klíčový rozdíl je zde v inicializaci mapy, která probíhá asynchronně a musíme tedy počkat, než můžeme zobrazit první highlight.
iOS
iOS API pro mapové polygony je bohužel z uvedených nejméně praktické. Zobrazení geometrií lze provést pomocí "overlays", které však neobsahují vizuální vlastnosti. Ty musíme poskytnout pomocí delegátu OverlayRenderer
, v našem případě v metodě OverlayRendererHandler
. Protože potřebujeme referenci na aktuálně zobrazenou instanci MapHighlight
, ulkládáme si ji jako datovou položku rendereru.
Zvýraznění v aplikaci
S hotovou mapou nyní zbývá dokončit hlavní logiku naší aplikace. Pro reprezentaci země napíšeme jednoduchou POCO třídu. Všimněme si, že kód používá ve svém konstruktoru novou syntaxi pro tuple-inicializaci.
Když dojde k inicializaci stránky, musíme naplnit seznam zemí. Metoda ReadCountryGeoJson()
vrací obsah souboru countries.geo.json
, který jsem přidal jako embedded resource projektu.
Data zemí jsou parsována do instance FeatureCollection
, což je specializovaný typ, který je součástí GeoJSON.Net. V této kolekci snadno najdeme Id
and name
vlastnosti jednotlivých zemí. Vlastnost SelectedItem
v našem ListView
je dvousměrně napojena na vlastnost SelectedCountry
:
Nakonec musíme implementovat metodu HighlightCountry
. Na základě výběru země najdeme odpovídající GeoJSON.Net feature a zkontrolujeme, zda jde o oblast složenou z jednoho čí o více mnohoúhelníků. Vytvoříme odpovídající instance MapPolygon
a z nich následně MapHighlight
.
Abychom zajistili, že uživatel skutečně vybranou oblast uvidí, počítáme její minimální a maximální souřadnice, a střed. Zavoláním metody MoveToRegion
pak tuto oblast vycentrujeme a přiblížíme v mapě. Všimněme si, že velikost oblasti násobíme číslem 1.2
, aby kolem zvýrazněné země byl volný okraj.
Ukázková aplikace
Zde je ukázka naší aplikace na UWP, Androidu a iOS. Kompletní zdrojový kód je k dispozici na mém GitHubu. [gallery columns="2" size="large" type="slideshow" ids="1876,1877,1878"]
Shrnutí
Ukázali jsme si, jak přidat novou funkcionalitu do výchozí Xamarin.Forms mapové komponenty a implementovali zvýrazňování mnohoúhelníkových oblastí nad mapou. Přestože jsme funkci demonstrovali na zvýrazňování zemí, je možné ji obecně použít pro mnoho dalších účelů.