Zvýraznění zemí na mapě v Xamarin.Forms

Xamarin

4 years ago

Tento článek byl vydán v rámci Xamarin UI July od Stevena Thewissena.

Xamarin.

Xamarin UI July

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.

Map highlighting on UWP

Map highlighting on UWP

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ů.