Přizpůsobení bodu na mapě
Tento článek ukazuje, jak vytvořit vlastní renderer pro ovládací prvek Mapa, který zobrazuje nativní mapu s přizpůsobeným špendlíkem a přizpůsobeným zobrazením dat připnutí na jednotlivých platformách.
Každé Xamarin.Forms zobrazení má doprovodný renderer pro každou platformu, která vytvoří instanci nativního ovládacího prvku. Když aplikace Map
v iOSu Xamarin.Forms vykresluje aplikaci, MapRenderer
vytvoří se instance třídy, která následně vytvoří instanci nativního MKMapView
ovládacího prvku. Na platformě Android třída MapRenderer
vytvoří instanci nativního MapView
ovládacího prvku. V Univerzální platforma Windows (UPW) třída MapRenderer
vytvoří instanci nativní MapControl
. Další informace o rendereru a nativních tříd ovládacích prvcích, které Xamarin.Forms řídí mapování, naleznete v tématu Renderer Základní třídy a nativní ovládací prvky.
Následující diagram znázorňuje vztah mezi Map
a odpovídajícími nativními ovládacími prvky, které ho implementují:
Proces vykreslování lze použít k implementaci přizpůsobení specifických pro platformu vytvořením vlastního rendereru pro každou platformu Map
. Postup je následující:
- Vytvořte Xamarin.Forms vlastní mapu.
- Využití vlastní mapy z Xamarin.Forms.
- Vytvořte vlastní renderer pro mapu na každé platformě.
Každá položka se teď bude probírat a implementovat CustomMap
renderer, který zobrazí nativní mapu s přizpůsobeným špendlíkem a přizpůsobeným zobrazením dat připnutí na jednotlivých platformách.
Poznámka:
Xamarin.Forms.Maps
před použitím musí být inicializován a nakonfigurován. Další informace najdete na webu Maps Control
.
Vytvoření vlastní mapy
Vlastní ovládací prvek mapy lze vytvořit podtřídou Map
třídy, jak je znázorněno v následujícím příkladu kódu:
public class CustomMap : Map
{
public List<CustomPin> CustomPins { get; set; }
}
Ovládací CustomMap
prvek se vytvoří v projektu knihovny .NET Standard a definuje rozhraní API pro vlastní mapu. Vlastní mapa zveřejňuje CustomPins
vlastnost, která představuje kolekci CustomPin
objektů, které budou vykresleny nativním mapovacím ovládacím prvku na každé platformě. Třída CustomPin
je uvedena v následujícím příkladu kódu:
public class CustomPin : Pin
{
public string Name { get; set; }
public string Url { get; set; }
}
Tato třída definuje CustomPin
jako dědění vlastností Pin
třídy a přidání Name
a Url
vlastnosti.
Využívání vlastní mapy
Na CustomMap
tento ovládací prvek lze odkazovat v XAML v projektu knihovny .NET Standard deklarováním oboru názvů pro jeho umístění a použitím předpony oboru názvů ve vlastním ovládacím prvku mapování. Následující příklad kódu ukazuje, jak CustomMap
může ovládací prvek využívat stránka XAML:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer">
<local:CustomMap x:Name="customMap"
MapType="Street" />
</ContentPage>
Předponu local
oboru názvů lze pojmenovat cokoli. clr-namespace
Hodnoty ale assembly
musí odpovídat podrobnostem vlastní mapy. Jakmile je obor názvů deklarován, předpona se použije k odkazování na vlastní mapu.
Následující příklad kódu ukazuje, jak CustomMap
může ovládací prvek využívat stránka jazyka C#:
public class MapPageCS : ContentPage
{
public MapPageCS()
{
CustomMap customMap = new CustomMap
{
MapType = MapType.Street
};
// ...
Content = customMap;
}
}
Instance CustomMap
se použije k zobrazení nativní mapy na jednotlivých platformách. MapType
Vlastnost nastaví styl zobrazení objektu Map
, s možnými hodnotami, které jsou definovány v výčtuMapType
.
Umístění mapy a špendlíky, které obsahuje, se inicializují, jak je znázorněno v následujícím příkladu kódu:
public MapPage()
{
// ...
CustomPin pin = new CustomPin
{
Type = PinType.Place,
Position = new Position(37.79752, -122.40183),
Label = "Xamarin San Francisco Office",
Address = "394 Pacific Ave, San Francisco CA",
Name = "Xamarin",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> { pin };
customMap.Pins.Add(pin);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));
}
Tato inicializace přidá vlastní špendlík a umístí zobrazení mapy s MoveToRegion
metodou, která změní pozici a úroveň přiblížení mapy vytvořením MapSpan
z Position
a a Distance
.
Do každého projektu aplikace je teď možné přidat vlastní renderer, který přizpůsobí nativní ovládací prvky mapování.
Vytvoření vlastního rendereru na jednotlivých platformách
Proces vytvoření vlastní třídy rendereru je následující:
- Vytvořte podtřídu
MapRenderer
třídy, která vykreslí vlastní mapu. - Přepište metodu
OnElementChanged
, která vykreslí vlastní mapování a logiku zápisu, aby ji přizpůsobila. Tato metoda se volá při vytvoření odpovídajícího Xamarin.Forms vlastního mapování. - Přidejte do vlastní třídy rendereru
ExportRenderer
atribut, který určí, že se použije k vykreslení Xamarin.Forms vlastní mapy. Tento atribut se používá k registraci vlastního rendereru v Xamarin.Forms.
Poznámka:
V každém projektu platformy je volitelné zadat vlastní renderer. Pokud není zaregistrovaný vlastní renderer, použije se výchozí renderer základní třídy ovládacího prvku.
Následující diagram znázorňuje zodpovědnosti jednotlivých projektů v ukázkové aplikaci spolu s relacemi mezi nimi:
Ovládací CustomMap
prvek je vykreslen pomocí tříd rendereru specifických pro platformu, které jsou odvozeny od třídy pro každou platformu MapRenderer
. Výsledkem je vykreslení každého CustomMap
ovládacího prvku pomocí ovládacích prvků specifických pro platformu, jak je znázorněno na následujících snímcích obrazovky:
MapRenderer
Třída zveřejňuje metoduOnElementChanged
, která je volána při Xamarin.Forms vytvoření vlastní mapování pro vykreslení odpovídajícího nativního ovládacího prvku. Tato metoda přebírá ElementChangedEventArgs
parametr, který obsahuje OldElement
a NewElement
vlastnosti. Tyto vlastnosti představují Xamarin.Forms prvek, ke kterému byl renderer připojen, a Xamarin.Forms prvek, ke kterému je renderer připojen, v uvedeném pořadí. V ukázkové aplikaci OldElement
bude vlastnost a NewElement
vlastnost bude obsahovat odkaz na CustomMap
null
instanci.
Přepsáná verze OnElementChanged
metody v každé třídě rendereru specifické pro platformu je místo pro provedení přizpůsobení nativního ovládacího prvku. Typový odkaz na nativní ovládací prvek, který se používá na platformě, je přístupný prostřednictvím Control
vlastnosti. Kromě toho lze prostřednictvím vlastnosti získat Element
odkaz na Xamarin.Forms vykreslovaný ovládací prvek.
Při přihlášení k odběru obslužných rutin událostí v OnElementChanged
metodě je potřeba věnovat pozornost, jak je znázorněno v následujícím příkladu kódu:
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged (e);
if (e.OldElement != null)
{
// Unsubscribe from event handlers
}
if (e.NewElement != null)
{
// Configure the native control and subscribe to event handlers
}
}
Nativní ovládací prvek by se měl nakonfigurovat a obslužné rutiny událostí odebírané pouze v případě, že je vlastní renderer připojený k novému Xamarin.Forms prvku. Podobně by se měly všechny obslužné rutiny událostí, které byly přihlášeny k odběru, odhlásit pouze tehdy, když je prvek, který renderer připojí ke změnám. Přijetí tohoto přístupu vám pomůže vytvořit vlastní renderer, který netrpí nevracením paměti.
Každá vlastní třída rendereru je zdobena ExportRenderer
atributem, který registruje renderer s Xamarin.Forms. Atribut má dva parametry – název typu vykreslovaného vlastního Xamarin.Forms ovládacího prvku a název typu vlastního rendereru. Předpona assembly
atributu určuje, že atribut se vztahuje na celé sestavení.
Následující části se týkají implementace jednotlivých vlastních tříd rendereru specifických pro platformu.
Vytvoření vlastního rendereru v iOSu
Následující snímky obrazovky znázorňují mapu před a po přizpůsobení:
V iOSu se pin označuje jako poznámka a může se jednat o vlastní obrázek nebo systémově definovaný špendlík různých barev. Poznámky můžou volitelně zobrazit bublinový popisek, který se zobrazí v reakci na uživatele, který vybere poznámku. Bublinový popisek zobrazí Label
vlastnosti a Address
vlastnosti Pin
instance s volitelnými zobrazeními zleva a doprava. Na snímku obrazovky výše je zobrazení levého přístupového objektu obrázek opice s pravým zobrazením příslušenství, které je tlačítkem Informace .
Následující příklad kódu ukazuje vlastní renderer pro platformu iOS:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.iOS
{
public class CustomMapRenderer : MapRenderer
{
UIView customPinView;
List<CustomPin> customPins;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
var nativeMap = Control as MKMapView;
if (nativeMap != null)
{
nativeMap.RemoveAnnotations(nativeMap.Annotations);
nativeMap.GetViewForAnnotation = null;
nativeMap.CalloutAccessoryControlTapped -= OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView -= OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView -= OnDidDeselectAnnotationView;
}
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
customPins = formsMap.CustomPins;
nativeMap.GetViewForAnnotation = GetViewForAnnotation;
nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView += OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView += OnDidDeselectAnnotationView;
}
}
// ...
}
}
Metoda OnElementChanged
provádí následující konfiguraci instance za předpokladu MKMapView
, že vlastní renderer je připojen k novému Xamarin.Forms prvku:
- Vlastnost
GetViewForAnnotation
je nastavena na metoduGetViewForAnnotation
. Tato metoda se volá, když se umístění poznámky zobrazí na mapě a slouží k přizpůsobení anotace před zobrazením. - Obslužné rutiny událostí pro ,
CalloutAccessoryControlTapped
DidSelectAnnotationView
aDidDeselectAnnotationView
události jsou registrovány. Tyto události se aktivují, když uživatel klepne na správné příslušenství v bublinovém popisku a když uživatel vybere a zruší výběr poznámky . Události se odhlásí pouze v případech, kdy je prvek, který renderer připojí ke změnám.
Zobrazení poznámky
Metoda GetViewForAnnotation
se volá, když se umístění anotace zobrazí na mapě a slouží k přizpůsobení anotace před zobrazením. Poznámka má dvě části:
MkAnnotation
– obsahuje název, podnadpis a umístění poznámky.MkAnnotationView
– obsahuje obrázek, který představuje poznámku, a volitelně popisek, který se zobrazí, když uživatel klepne na poznámku.
Metoda GetViewForAnnotation
přijme IMKAnnotation
, která obsahuje data poznámek a vrátí MKAnnotationView
zobrazení na mapě a je znázorněna v následujícím příkladu kódu:
protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
var customPin = GetCustomPin(annotation as MKPointAnnotation);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
annotationView = mapView.DequeueReusableAnnotation(customPin.Name);
if (annotationView == null)
{
annotationView = new CustomMKAnnotationView(annotation, customPin.Name);
annotationView.Image = UIImage.FromFile("pin.png");
annotationView.CalloutOffset = new CGPoint(0, 0);
annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
((CustomMKAnnotationView)annotationView).Name = customPin.Name;
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
}
annotationView.CanShowCallout = true;
return annotationView;
}
Tato metoda zajistí, že se poznámka zobrazí jako vlastní obrázek, nikoli jako systémový pin kód, a že se při klepnutí na poznámku zobrazí popisek, který bude obsahovat další obsah vlevo a vpravo od názvu a adresy poznámky. To se provádí takto:
- Volá se
GetCustomPin
metoda pro vrácení vlastních dat připnutí pro anotaci. - Aby se ušetřila paměť, je zobrazení poznámek ve fondu pro opakované použití s voláním
DequeueReusableAnnotation
. - Třída
CustomMKAnnotationView
rozšiřujeMKAnnotationView
třídu oName
vlastnostiUrl
, které odpovídají identickým vlastnostemCustomPin
v instanci. Vytvoří se nová instance za předpokladuCustomMKAnnotationView
, že poznámka jenull
:- Vlastnost
CustomMKAnnotationView.Image
je nastavena na obrázek, který bude představovat poznámku na mapě. - Vlastnost
CustomMKAnnotationView.CalloutOffset
je nastavena naCGPoint
hodnotu, která určuje, že popisek bude zacentrován nad poznámkou. - Vlastnost
CustomMKAnnotationView.LeftCalloutAccessoryView
je nastavena na obrázek opice, která se zobrazí nalevo od názvu a adresy poznámky. - Vlastnost
CustomMKAnnotationView.RightCalloutAccessoryView
je nastavena na tlačítko Informace , které se zobrazí vpravo od názvu a adresy poznámky. - Vlastnost je nastavena
CustomMKAnnotationView.Name
naCustomPin.Name
vlastnost vrácenou metodouGetCustomPin
. To umožňuje identifikaci poznámek, aby bylo možné popisek dále přizpůsobit, pokud je to žádoucí. - Vlastnost je nastavena
CustomMKAnnotationView.Url
naCustomPin.Url
vlastnost vrácenou metodouGetCustomPin
. Adresa URL se přepne, když uživatel klepne na tlačítko zobrazené v pravém zobrazení přístupového popisku.
- Vlastnost
- Vlastnost
MKAnnotationView.CanShowCallout
je nastavena taktrue
, aby se bublinový popisek zobrazil při klepnutí na poznámku. - Pro zobrazení na mapě se vrátí poznámka.
Výběr poznámky
Když uživatel klepne na poznámku, DidSelectAnnotationView
aktivuje se událost, která následně spustí metodu OnDidSelectAnnotationView
:
void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e)
{
CustomMKAnnotationView customView = e.View as CustomMKAnnotationView;
customPinView = new UIView();
if (customView.Name.Equals("Xamarin"))
{
customPinView.Frame = new CGRect(0, 0, 200, 84);
var image = new UIImageView(new CGRect(0, 0, 200, 84));
image.Image = UIImage.FromFile("xamarin.png");
customPinView.AddSubview(image);
customPinView.Center = new CGPoint(0, -(e.View.Frame.Height + 75));
e.View.AddSubview(customPinView);
}
}
Tato metoda rozšiřuje existující bublinový popisek (který obsahuje zobrazení levého a pravého přístupového objektu) přidáním UIView
instance, která obsahuje obrázek loga Xamarinu za předpokladu, že vybraná poznámka má jeho Name
vlastnost nastavena na Xamarin
. To umožňuje scénáře, ve kterých se pro různé poznámky dají zobrazit různé bublinové popisky. Instance UIView
se zobrazí uprostřed nad existujícím popisem.
Klepnutí na pravé zobrazení přístupového popisku
Když uživatel klepne na tlačítko Informace v pravém zobrazení přístupového popisku, CalloutAccessoryControlTapped
událost se aktivuje, což následně spustí metodu OnCalloutAccessoryControlTapped
:
void OnCalloutAccessoryControlTapped(object sender, MKMapViewAccessoryTappedEventArgs e)
{
CustomMKAnnotationView customView = e.View as CustomMKAnnotationView;
if (!string.IsNullOrWhiteSpace(customView.Url))
{
UIApplication.SharedApplication.OpenUrl(new Foundation.NSUrl(customView.Url));
}
}
Tato metoda otevře webový prohlížeč a přejde na adresu uloženou CustomMKAnnotationView.Url
ve vlastnosti. Všimněte si, že adresa byla definována při vytváření CustomPin
kolekce v projektu knihovny .NET Standard.
Zrušení výběru poznámky
Když se zobrazí poznámka a uživatel klepne na mapu, DidDeselectAnnotationView
aktivuje se událost, která následně spustí metodu OnDidDeselectAnnotationView
:
void OnDidDeselectAnnotationView(object sender, MKAnnotationViewEventArgs e)
{
if (!e.View.Selected)
{
customPinView.RemoveFromSuperview();
customPinView.Dispose();
customPinView = null;
}
}
Tato metoda zajistí, že pokud není vybraný existující popisek, přestane se zobrazovat i rozšířená část popisku (obrázek loga Xamarinu) a uvolní se její prostředky.
Další informace o přizpůsobení MKMapView
instance najdete v mapách iOS.
Vytvoření vlastního rendereru v Androidu
Následující snímky obrazovky znázorňují mapu před a po přizpůsobení:
V Androidu se špendlík nazývá značka a může to být vlastní obrázek nebo značka definovaná systémem různých barev. Značky můžou zobrazit informační okno, které se zobrazí v reakci na uživatele, který klepne na značku. V okně s informacemi se Label
zobrazí vlastnosti Pin
instance Address
a dá se přizpůsobit tak, aby zahrnovalo další obsah. Najednou se ale dá zobrazit jenom jedno okno s informacemi.
Následující příklad kódu ukazuje vlastní renderer pro platformu Android:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public CustomMapRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
}
}
protected override void OnMapReady(GoogleMap map)
{
base.OnMapReady(map);
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
}
...
}
}
Za předpokladu, že vlastní renderer je připojen k novému Xamarin.Forms prvku, OnElementChanged
metoda načte seznam vlastních špendlíků z ovládacího prvku. GoogleMap
Jakmile je instance k dispozici, OnMapReady
vyvolá se přepsání. Tato metoda zaregistruje obslužnou rutinu InfoWindowClick
události pro událost, která se aktivuje při kliknutí na informační okno a odhlásí se pouze v případě, že je renderer připojen ke změnám. Přepsání OnMapReady
také volá metodu SetInfoWindowAdapter
k určení, že CustomMapRenderer
instance třídy poskytne metody pro přizpůsobení informačního okna.
Třída CustomMapRenderer
implementuje GoogleMap.IInfoWindowAdapter
rozhraní pro přizpůsobení informačního okna. Toto rozhraní určuje, že musí být implementovány následující metody:
public Android.Views.View GetInfoWindow(Marker marker)
– Tato metoda je volána k vrácení vlastního informačního okna pro značku. Pokud se vrátínull
, použije se výchozí vykreslování oken. Pokud vrátí hodnotuView
, pak seView
umístí do rámce informačního okna.public Android.Views.View GetInfoContents(Marker marker)
– Tato metoda je volána k vráceníView
obsahující obsah informačního okna a bude volána pouze v případě, žeGetInfoWindow
metoda vrátínull
. Pokud se vrátínull
, použije se výchozí vykreslení obsahu okna s informacemi.
V ukázkové aplikaci je přizpůsobený pouze obsah informačního okna, takže GetInfoWindow
metoda se vrátí null
k povolení.
Přizpůsobení značky
Ikonu použitou k reprezentaci značky lze přizpůsobit voláním MarkerOptions.SetIcon
metody. Toho lze dosáhnout přepsáním CreateMarker
metody, která se vyvolá pro každou Pin
přidanou do mapy:
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
marker.SetSnippet(pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
return marker;
}
Tato metoda vytvoří novou MarkerOption
instanci pro každou Pin
instanci. Po nastavení pozice, popisku a adresy značky se její ikona nastaví pomocí SetIcon
metody. Tato metoda přebírá BitmapDescriptor
objekt obsahující data potřebná k vykreslení ikony, se BitmapDescriptorFactory
třídou poskytující pomocné metody pro zjednodušení vytváření BitmapDescriptor
. Další informace o použití BitmapDescriptorFactory
třídy k přizpůsobení značky naleznete v tématu Přizpůsobení značky.
Poznámka:
V případě potřeby lze metodu GetMarkerForPin
vyvolat ve vykreslovacím modulu mapování, která načte Marker
z objektu Pin
.
Přizpůsobení informačního okna
Když uživatel klepne na značku, GetInfoContents
spustí se metoda za předpokladu GetInfoWindow
, že metoda vrátí null
. Následující příklad kódu ukazuje metodu GetInfoContents
:
public Android.Views.View GetInfoContents(Marker marker)
{
var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;
if (inflater != null)
{
Android.Views.View view;
var customPin = GetCustomPin(marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
if (customPin.Name.Equals("Xamarin"))
{
view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
}
else
{
view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
}
var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
if (infoTitle != null)
{
infoTitle.Text = marker.Title;
}
if (infoSubtitle != null)
{
infoSubtitle.Text = marker.Snippet;
}
return view;
}
return null;
}
Tato metoda vrátí View
obsah informačního okna. To se provádí takto:
- Načte
LayoutInflater
se instance. Slouží k vytvoření instance souboru XML rozložení do odpovídajícíhoView
souboru . - Volá se
GetCustomPin
metoda pro vrácení vlastních dat připnutí pro informační okno. - Rozložení
XamarinMapInfoWindow
se nafoukne, pokudCustomPin.Name
je vlastnost rovnaXamarin
.MapInfoWindow
Jinak se rozložení nafoukne. To umožňuje scénáře, ve kterých se pro různé značky dají zobrazit různá rozložení okna s informacemi. - Prostředky se
InfoWindowSubtitle
InfoWindowTitle
načítají z nafouštěného rozložení a jejichText
vlastnosti jsou nastaveny na odpovídající data z instance za předpokladuMarker
, že prostředky nejsounull
. - Instance
View
se vrátí pro zobrazení na mapě.
Poznámka:
Informační okno není živé View
. Místo toho Android převede View
na statický rastrový obrázek a zobrazí ho jako obrázek. To znamená, že zatímco informační okno může reagovat na událost kliknutí, nemůže reagovat na žádné dotykové události nebo gesta a jednotlivé ovládací prvky v informačním okně nemohou reagovat na vlastní události kliknutí.
Kliknutí na okno Informace
Když uživatel klikne na informační okno, InfoWindowClick
událost se aktivuje, což následně spustí metodu OnInfoWindowClick
:
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
var customPin = GetCustomPin(e.Marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
if (!string.IsNullOrWhiteSpace(customPin.Url))
{
var url = Android.Net.Uri.Parse(customPin.Url);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
Tato metoda otevře webový prohlížeč a přejde na adresu uloženou Url
ve vlastnosti načtené CustomPin
instance pro Marker
objekt . Všimněte si, že adresa byla definována při vytváření CustomPin
kolekce v projektu knihovny .NET Standard.
Další informace o přizpůsobení MapView
instance najdete v tématu Rozhraní Maps API.
Vytvoření vlastního rendereru na Univerzální platforma Windows
Následující snímky obrazovky znázorňují mapu před a po přizpůsobení:
Při UPW se špendlík nazývá ikona mapy a může to být vlastní obrázek nebo výchozí obrázek definovaný systémem. Ikona mapy může zobrazit UserControl
ikonu , která se zobrazí v reakci na uživatele klepnutím na ikonu mapy. Může UserControl
zobrazit libovolný obsah, včetně Label
vlastností a Address
vlastností Pin
instance.
Následující příklad kódu ukazuje vlastní renderer UPW:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.UWP
{
public class CustomMapRenderer : MapRenderer
{
MapControl nativeMap;
List<CustomPin> customPins;
XamarinMapOverlay mapOverlay;
bool xamarinOverlayShown = false;
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
nativeMap.MapElementClick -= OnMapElementClick;
nativeMap.Children.Clear();
mapOverlay = null;
nativeMap = null;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
nativeMap = Control as MapControl;
customPins = formsMap.CustomPins;
nativeMap.Children.Clear();
nativeMap.MapElementClick += OnMapElementClick;
foreach (var pin in customPins)
{
var snPosition = new BasicGeoposition { Latitude = pin.Pin.Position.Latitude, Longitude = pin.Pin.Position.Longitude };
var snPoint = new Geopoint(snPosition);
var mapIcon = new MapIcon();
mapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///pin.png"));
mapIcon.CollisionBehaviorDesired = MapElementCollisionBehavior.RemainVisible;
mapIcon.Location = snPoint;
mapIcon.NormalizedAnchorPoint = new Windows.Foundation.Point(0.5, 1.0);
nativeMap.MapElements.Add(mapIcon);
}
}
}
...
}
}
Metoda OnElementChanged
provádí následující operace za předpokladu, že vlastní renderer je připojen k novému Xamarin.Forms prvku:
- Vymaže
MapControl.Children
kolekci, aby před registrací obslužné rutiny události proMapElementClick
událost odebrala z mapy všechny existující prvky uživatelského rozhraní. Tato událost se aktivuje, když uživatel klepne nebo klikne naMapElement
ikonu aMapControl
zruší odběr pouze v případě, že je vykreslovací prvek připojený ke změnám. - Každý špendlík v
customPins
kolekci se zobrazí ve správném zeměpisném umístění na mapě následujícím způsobem:- Umístění špendlíku se vytvoří jako
Geopoint
instance. - Vytvoří
MapIcon
se instance představující špendlík. - Obrázek použitý k reprezentaci
MapIcon
je určen nastavenímMapIcon.Image
vlastnosti. Obrázek ikony mapy ale není vždy zaručen, že se zobrazí, protože může být zakrytý jinými prvky na mapě. Proto je vlastnost ikonyCollisionBehaviorDesired
mapy nastavena naMapElementCollisionBehavior.RemainVisible
, aby se zajistilo, že zůstane viditelný. - Umístění
MapIcon
je určeno nastavenímMapIcon.Location
vlastnosti. - Vlastnost
MapIcon.NormalizedAnchorPoint
je nastavena na přibližné umístění ukazatele na obrázku. Pokud tato vlastnost zachová výchozí hodnotu (0,0), která představuje levý horní roh obrázku, změny na úrovni přiblížení mapy můžou vést k tomu, že obrázek odkazuje na jiné místo. - Instance
MapIcon
se přidá doMapControl.MapElements
kolekce. Výsledkem je zobrazení ikony mapy na kartěMapControl
.
- Umístění špendlíku se vytvoří jako
Poznámka:
Při použití stejného obrázku pro více ikon RandomAccessStreamReference
mapy by se instance měla deklarovat na úrovni stránky nebo aplikace, aby byl nejlepší výkon.
Zobrazení UserControl
Když uživatel klepne na ikonu mapy, spustí se OnMapElementClick
metoda. Následující příklad kódu ukazuje tuto metodu:
private void OnMapElementClick(MapControl sender, MapElementClickEventArgs args)
{
var mapIcon = args.MapElements.FirstOrDefault(x => x is MapIcon) as MapIcon;
if (mapIcon != null)
{
if (!xamarinOverlayShown)
{
var customPin = GetCustomPin(mapIcon.Location.Position);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
if (customPin.Name.Equals("Xamarin"))
{
if (mapOverlay == null)
{
mapOverlay = new XamarinMapOverlay(customPin);
}
var snPosition = new BasicGeoposition { Latitude = customPin.Position.Latitude, Longitude = customPin.Position.Longitude };
var snPoint = new Geopoint(snPosition);
nativeMap.Children.Add(mapOverlay);
MapControl.SetLocation(mapOverlay, snPoint);
MapControl.SetNormalizedAnchorPoint(mapOverlay, new Windows.Foundation.Point(0.5, 1.0));
xamarinOverlayShown = true;
}
}
else
{
nativeMap.Children.Remove(mapOverlay);
xamarinOverlayShown = false;
}
}
}
Tato metoda vytvoří UserControl
instanci, která zobrazí informace o špendlíku. To se provádí takto:
- Instance
MapIcon
se načte. - Volá se
GetCustomPin
metoda pro vrácení vlastních dat připnutí, která se zobrazí. - Vytvoří se
XamarinMapOverlay
instance pro zobrazení vlastních dat připnutí. Tato třída je uživatelský ovládací prvek. - Zeměpisné umístění, ve kterém se má instance
MapControl
zobrazitXamarinMapOverlay
, se vytvoří jakoGeopoint
instance. - Instance
XamarinMapOverlay
se přidá doMapControl.Children
kolekce. Tato kolekce obsahuje prvky uživatelského rozhraní XAML, které se zobrazí na mapě. - Zeměpisné umístění
XamarinMapOverlay
instance na mapě je nastaveno volánímSetLocation
metody. - Relativní umístění v
XamarinMapOverlay
instanci, která odpovídá zadanému umístění, je nastaveno volánímSetNormalizedAnchorPoint
metody. Tím se zajistí, že se změny na úrovni přiblížení mapy zobrazí vždyXamarinMapOverlay
ve správném umístění.
Pokud se na mapě už zobrazují informace o špendlíku, klepnutím na mapu odeberete XamarinMapOverlay
instanci z MapControl.Children
kolekce.
Klepnutí na tlačítko Informace
Když uživatel klepne na tlačítko Informace v ovládacím XamarinMapOverlay
prvku uživatele, Tapped
událost se aktivuje, která následně spustí metodu OnInfoButtonTapped
:
private async void OnInfoButtonTapped(object sender, TappedRoutedEventArgs e)
{
await Launcher.LaunchUriAsync(new Uri(customPin.Url));
}
Tato metoda otevře webový prohlížeč a přejde na adresu uloženou Url
ve vlastnosti CustomPin
instance. Všimněte si, že adresa byla definována při vytváření CustomPin
kolekce v projektu knihovny .NET Standard.
Další informace o přizpůsobení MapControl
instance najdete v tématu Mapy a přehled polohy na webu MSDN.