.NET 多平台应用 UI (.NET MAUI) Map 控件是用于显示和批注地图的跨平台视图。 该 Map 控件在每个平台上使用本机地图控件,并由 Microsoft.Maui.Controls.Maps NuGet 包提供。
重要
由于 WinUI 中缺少地图控件,因此 Windows 不支持该 Map 控件。 但是,CommunityToolkit.Maui.Maps NuGet 包通过 Windows 上的 WebView
提供对必应地图的访问权限。 有关详细信息,请参阅 入门。
设置
该 Map 控件在每个平台上使用原生地图控件。 这为用户提供了快速、熟悉的地图体验,但意味着需要一些配置步骤来遵守每个平台 API 要求。
地图初始化
控件 Map 由 Microsoft.Maui.Controls.Maps NuGet 包提供,该包应添加到 .NET MAUI 应用项目。
安装 NuGet 包后,必须通过在MauiProgram
类的CreateMauiApp
方法中调用MauiAppBuilder
对象的UseMauiMaps方法来初始化它:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
.UseMauiMaps();
return builder.Build();
}
}
添加和初始化 NuGet 包后, Map 可以在项目中使用 API。
平台配置
在显示地图之前,Android 上需要其他配置。 此外,在 iOS、Android 和 Mac Catalyst 上,访问用户的位置需要向应用授予位置权限。
iOS 和 Mac Catalyst
在 iOS 和 Mac Catalyst 上显示和与地图交互不需要任何其他配置。 但是,若要访问位置服务,应在 Info.plist 中设置所需的位置服务请求。 这些通常为以下一个或多个:
-
NSLocationAlwaysAndWhenInUseUsageDescription
– 用于随时使用位置服务。 -
NSLocationWhenInUseUsageDescription
– 用于在应用使用时使用位置服务。
有关详细信息,请参阅选择要在 developer.apple.com 请求的位置服务授权 。
Info.plist 中这些键的 XML 表示形式如下所示。 应更新 string
值以反映应用如何使用位置信息:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your ___location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your ___location when your app is being used?</string>
然后,当应用尝试访问用户的位置时,将显示提示,请求访问:
安卓
在 Android 上显示和交互地图的配置过程是:
- 获取 Google Maps API 密钥并将其添加到应用清单。
- 在清单中指定 Google Play 服务版本号。
- [可选]在清单中指定位置权限。
- [可选]在清单中指定WRITE_EXTERNAL_STORAGE权限。
获取 Google Maps API 密钥
若要在 Map Android 上使用控件,必须生成 API 密钥,该密钥将由该控件依赖 Android 的 Google Maps SDKMap 使用。 为此,请按照 Google Cloud Console 中的“设置 ”中的说明作,并在 developers.google.com 上使用 API 密钥 。
获取 API 密钥后,必须将其添加到 <application>
元素中,方法是在 Platforms/Android/AndroidManifest.xml 文件中将其指定为 com.google.android.geo.API_KEY
元数据的值:
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
<meta-data android:name="com.google.android.geo.API_KEY" android:value="PASTE-YOUR-API-KEY-HERE" />
</application>
这会将 API 密钥嵌入清单中。 如果没有有效的 API 密钥,控件 Map 将显示一个空白网格。
注释
com.google.android.geo.API_KEY
是 API 密钥的建议元数据名称。 使用此名称的密钥可用于在 Android 上对多个基于 Google Maps 的 API 进行身份验证。 为了向后兼容, com.google.android.maps.v2.API_KEY
可以使用元数据名称,但只允许对 Android Maps API v2 进行身份验证。 应用只能指定其中一个 API 密钥元数据名称。
指定 Google Play 服务版本号
在 AndroidManifest.xml元素中添加<application>
以下声明:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
这会将应用编译的 Google Play 服务版本嵌入清单中。
指定位置权限
如果你的应用需要访问用户的位置,则必须在清单中添加 ACCESS_COARSE_LOCATION
或 ACCESS_FINE_LOCATION
权限(或两者)作为 <manifest>
元素的子元素来请求权限。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<!-- Required to access the user's ___location -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
该 ACCESS_COARSE_LOCATION
权限允许 API 使用 WiFi 或移动数据(或两者)来确定设备的位置。 该 ACCESS_FINE_LOCATION
权限允许 API 使用全局定位系统(GPS)、WiFi 或移动数据来确定尽可能精确的位置。
然后,当应用尝试访问用户的位置时,将显示提示,请求访问:
或者,可以在 Visual Studio 的 Android 清单编辑器中启用这些权限。
指定WRITE_EXTERNAL_STORAGE权限
如果您的应用面向 API 22 或更低版本,则需要将WRITE_EXTERNAL_STORAGE
权限作为<manifest>
元素的子元素添加到清单文件中。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
如果应用面向 API 23 或更高版本,则不需要这样做。
地图控件
该 Map 类定义用于控制地图外观和行为的以下属性:
-
IsShowingUser
,类型bool
,指示地图是否显示用户的当前位置。 -
ItemsSource
,类型为IEnumerable
,指定用于显示的固定项集合IEnumerable
。 -
ItemTemplate
,类型 DataTemplate,指定 DataTemplate 应用于所显示引脚集合中的每个项。 -
ItemTemplateSelector
,类型为DataTemplateSelector,它指定了在运行时将用于选择某个引脚的DataTemplateSelector,以确定DataTemplate。 -
IsScrollEnabled
类型的bool
决定是否允许地图滚动。 -
IsTrafficEnabled
的类型为bool
,用于指示交通数据是否叠加在地图上。 - 类型为
bool
的IsZoomEnabled
确定地图是否可以缩放。 -
MapElements
类型IList<MapElement>
,表示地图上的元素列表,如多边形和折线。 -
MapType
类型MapType
,指示地图的显示样式。 -
Pins
,类型IList<Pin>
,表示地图上的图钉列表。 -
VisibleRegion
类型MapSpan
,返回地图当前显示的区域。
这些属性(除了MapElements
、Pins
和VisibleRegion
属性外)由BindableProperty对象提供支持,这意味着它们可以作为数据绑定的目标。
该 Map 类还定义 MapClicked
在点击地图时触发的事件。
MapClickedEventArgs
事件附带的对象拥有一个属性,名为Location
,其类型为Location
。 触发事件时,该 Location
属性将设置为点击的地图位置。 有关类 Location
的信息,请参阅 位置和距离。
有关ItemsSource
ItemTemplate
ItemTemplateSelector
属性的信息,请参阅显示固定集合。
显示地图
要显示 A Map,可以将其添加到布局或页面中:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
<maps:Map x:Name="map" />
</ContentPage>
等效的 C# 代码为:
using Map = Microsoft.Maui.Controls.Maps.Map;
namespace WorkingWithMaps
{
public class MapTypesPageCode : ContentPage
{
public MapTypesPageCode()
{
Map map = new Map();
Content = map;
}
}
}
此示例调用默认 Map 构造函数,该构造函数以夏威夷 Maui 上的地图为中心::
或者, MapSpan
可以将参数传递给 Map 构造函数,以在加载地图时设置地图的中心点和缩放级别。 有关详细信息,请参阅 在地图上显示特定位置。
重要
.NET MAUI 有两 Map
种类型 - Microsoft.Maui.Controls.Maps.Map 和 Microsoft.Maui.ApplicationModel.Map。
Microsoft.Maui.ApplicationModel由于命名空间是 .NET MAUI 的指令之一,因此使用Microsoft.Maui.Controls.Maps.Map代码中的global using
控件时,必须完全限定Map
使用情况或使用别名。
地图类型
Map.MapType
该属性可以设置为MapType
枚举成员,以定义地图的显示样式。
MapType
枚举定义以下成员:
-
Street
指定将显示街道地图。 -
Satellite
指定将显示包含卫星影像的地图。 -
Hybrid
指定将显示合并街道和卫星数据的地图。
默认情况下,Map将显示街道地图,如果MapType
属性未定义。 或者,可以将MapType
属性设置为MapType
枚举成员之一。
<maps:Map MapType="Satellite" />
等效的 C# 代码为:
Map map = new Map
{
MapType = MapType.Satellite
};
在地图上显示特定位置
通过将参数传递给MapSpan
Map构造函数,可以设置加载地图时要显示的地图区域:
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
<x:Double>0.01</x:Double>
<x:Double>0.01</x:Double>
</x:Arguments>
</maps:MapSpan>
</x:Arguments>
</maps:Map>
</ContentPage>
等效的 C# 代码为:
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Location ___location = new Location(36.9628066, -122.0194722);
MapSpan mapSpan = new MapSpan(___location, 0.01, 0.01);
Map map = new Map(mapSpan);
此示例创建一个 Map 对象,该对象显示由 MapSpan
该对象指定的区域。 该 MapSpan
对象以 Location
对象表示的纬度和经度为中心,跨越 0.01 纬度和 0.01 经度。 有关类 Location
的信息,请参阅 位置和距离。 有关在 XAML 中传递参数的信息,请参阅 XAML 中的传递参数。
结果是,当地图显示时,它以特定位置为中心,并跨越特定的纬度和经度范围。
创建 MapSpan 对象
有多种方法可用于创建 MapSpan
对象。 常见的方法是向构造函数提供所需的参数 MapSpan
。 这些是由 Location
对象表示的纬度和经度,以及 double
表示由 MapSpan
跨越的纬度和经度的值。 有关类 Location
的信息,请参阅 位置和距离。
或者,类中有 MapSpan
三种方法返回新 MapSpan
对象:
-
ClampLatitude
返回与方法的类实例相同的LongitudeDegrees
值MapSpan
,以及由其north
和south
参数定义的半径。 -
FromCenterAndRadius
返回由其Location
和Distance
参数定义的一个MapSpan
。 -
WithZoom
返回一个与类实例具有相同中心的MapSpan
,但其半径被double
参数乘以。
有关结构的信息 Distance
,请参阅 位置和距离。
创建一 MapSpan
个属性后,可以访问以下属性来检索有关它的数据:
-
Center
,类型Location
,表示地理中心MapSpan
中的位置。 -
LatitudeDegrees
,类型为double
,表示MapSpan
所跨越的纬度度数。 -
LongitudeDegrees
,类型为double
,表示由MapSpan
跨越的经度。 -
Radius
,类型为Distance
,表示MapSpan
半径。
移动地图
Map.MoveToRegion
可以调用此方法来更改地图的位置和缩放级别。 此方法接受一个 MapSpan
参数,该参数定义要显示的地图区域及其缩放级别。
以下代码演示了在地图上移动所显示区域的示例:
using Microsoft.Maui.Maps;
using Microsoft.Maui.Controls.Maps.Map;
...
MapSpan mapSpan = MapSpan.FromCenterAndRadius(___location, Distance.FromKilometers(0.444));
map.MoveToRegion(mapSpan);
缩放地图
可以在不更改其位置的情况下更改其 Map 缩放级别。 这可以通过使用地图 UI 来实现,也可以通过调用将当前位置用作Location
参数的参数以编程MoveToRegion
MapSpan
方式实现:
double zoomLevel = 0.5;
double latlongDegrees = 360 / (Math.Pow(2, zoomLevel));
if (map.VisibleRegion != null)
{
map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees));
}
在此示例中,调用MoveToRegion
方法并传入MapSpan
参数,该参数通过Map.VisibleRegion
属性指定地图的当前位置,并将缩放级别指定为纬度和经度的度数。 总体结果是地图的缩放级别已更改,但其位置不是。 在地图上实现缩放的替代方法是使用 MapSpan.WithZoom
该方法控制缩放因子。
重要
缩放地图无论是通过地图 UI 还是以编程方式,都需要确保Map.IsZoomEnabled
属性为true
。 有关此属性的详细信息,请参阅 “禁用缩放”。
自定义地图行为
通过设置Map的某些属性和处理MapClicked
事件,可以自定义其行为。
注释
可以通过自定义其处理程序来实现其他地图行为自定义。 有关详细信息,请参阅 使用处理程序自定义控件。
显示交通情况数据
类 Map 定义一个 IsTrafficEnabled
类型 bool
属性。 默认情况下,此属性 false
指示不会在地图上覆盖流量数据。 如果此属性设置为 true
,流量数据将覆盖在地图上:
<maps:Map IsTrafficEnabled="true" />
等效的 C# 代码为:
Map map = new Map
{
IsTrafficEnabled = true
};
禁用滚动
类 Map 定义一个 IsScrollEnabled
类型 bool
属性。 默认情况下,此属性 true
指示允许地图滚动。 如果此属性设置为 false
,映射将不会滚动:
<maps:Map IsScrollEnabled="false" />
等效的 C# 代码为:
Map map = new Map
{
IsScrollEnabled = false
};
禁用缩放
类 Map 定义一个 IsZoomEnabled
类型 bool
属性。 默认情况下,此属性 true
指示可以在地图上执行缩放。 如果此属性设置为 false
,则无法缩放地图:
<maps:Map IsZoomEnabled="false" />
等效的 C# 代码为:
Map map = new Map
{
IsZoomEnabled = false
};
显示用户的位置
类 Map 定义一个 IsShowingUser
类型 bool
属性。 默认情况下,此属性 false
指示地图未显示用户的当前位置。 当此属性设置为 true
时,地图显示用户的当前位置:
<maps:Map IsShowingUser="true" />
等效的 C# 代码为:
Map map = new Map
{
IsShowingUser = true
};
重要
访问用户的位置需要向应用程序授予位置权限。 有关详细信息,请参阅 平台配置。
地图点击次数
Map 类定义了一个事件,该事件在点击地图时会触发。 事件附带的MapClickedEventArgs
对象具有一个名为Location
的属性,类型为Location
。 触发事件时,该 Location
属性将设置为点击的地图位置。 有关类 Location
的信息,请参阅 位置和距离。
下面的代码示例演示事件的 MapClicked
事件处理程序:
void OnMapClicked(object sender, MapClickedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"MapClick: {e.Location.Latitude}, {e.Location.Longitude}");
}
在此示例中, OnMapClicked
事件处理程序输出表示点击的地图位置的纬度和经度。 事件处理程序必须注册用于 MapClicked
事件。
<maps:Map MapClicked="OnMapClicked" />
等效的 C# 代码为:
Map map = new Map();
map.MapClicked += OnMapClicked;
位置和距离
命名空间 Microsoft.Maui.Devices.Sensors
包含一个类 Location
,通常用于定位地图及其标记。 命名空间 Microsoft.Maui.Maps
包含一个 Distance
结构,该结构可以选择在定位地图时使用。
位置
该 Location
类将位置封装为存储的纬度和经度值。 此类定义了以下属性:
-
Accuracy
,类型double?
,表示以米为单位的水平Location
精度。 -
Altitude
,类型double?
,表示在由AltitudeReferenceSystem
属性指定的参考系统中,以米为单位的高度。 -
AltitudeReferenceSystem
,类型为AltitudeReferenceSystem
,指定提供海拔值的参考系统。 -
Course
,表示double?
相对于真北的度值。 -
IsFromMockProvider
的类型为bool
,用于指示位置是来自 GPS 还是来自模拟位置提供程序。 -
Latitude
,类型为double
,表示位置的纬度,以小数度数表示。 -
Longitude
,类型double
,表示位置的经度,以十进小数度表示。 -
Speed
,类型double?
,表示每秒速度(以米为单位)。 -
Timestamp
,类型DateTimeOffset
,表示创建时的Location
时间戳。 -
VerticalAccuracy
,类型double?
,指定以米为单位的Location
垂直精度。
Location
对象是通过使用 Location
中的一个构造函数重载来创建的,这些重载通常至少需要指定为 double
值的纬度和经度参数:
Location ___location = new Location(36.9628066, -122.0194722);
创建 Location
对象时,纬度值将固定在 -90.0 和 90.0 之间,经度值将固定在 -180.0 和 180.0 之间。
注释
该 GeographyUtils
类具有将 ToRadians
值从度转换为 double
弧度的扩展方法,以及将 ToDegrees
值从弧度转换为 double
度的扩展方法。
该 Location
类还具有 CalculateDistance
计算两个位置之间的距离的方法。
距离
Distance
结构体封装了一段存储为double
值的距离,该值表示以米为单位的距离。 此结构定义三个只读属性:
-
Kilometers
,类型double
,表示跨越的Distance
距离(以公里为单位)。 -
Meters
,类型为double
,表示Distance
所跨越的距离,以米为单位。 -
Miles
,属于double
类型,表示Distance
所覆盖的距离(以英里为单位)。
Distance
对象可以使用Distance
构造函数创建,该构造函数需要一个作为double
指定的米参数:
Distance distance = new Distance(1450.5);
或者,可以使用FromKilometers
、FromMeters
、FromMiles
和BetweenPositions
工厂方法创建Distance
对象。
Distance distance1 = Distance.FromKilometers(1.45); // argument represents the number of kilometers
Distance distance2 = Distance.FromMeters(1450.5); // argument represents the number of meters
Distance distance3 = Distance.FromMiles(0.969); // argument represents the number of miles
Distance distance4 = Distance.BetweenPositions(location1, location2);
引 脚
该 Map 控件允许使用对象标记 Pin
位置。 地图标记Pin
在点击时打开信息窗口。
在将Pin
对象添加到Map.Pins
集合时,图钉将在地图上呈现。
Pin
类具有以下属性:
-
Address
,类型string
,通常表示固定位置的地址。 但是,它可以是任何string
内容,而不仅仅是地址。 -
Label,类型
string
,通常表示置顶标题。 -
Location
,类型为Location
,表示位置的纬度和经度。 -
Type
,类型PinType
,表示引脚的类型。
这些属性由 BindableProperty 对象提供支持,这意味着可以是 Pin
数据绑定的目标。 有关数据绑定 Pin
对象的更多信息,请参阅 显示引脚集合。
此外,类 Pin
定义 MarkerClicked
和 InfoWindowClicked
事件。
MarkerClicked
点击图钉时会触发该事件,InfoWindowClicked
在点击信息窗口时触发该事件。
PinClickedEventArgs
伴随这两个事件的对象具有一个HideInfoWindow
属性,其类型为bool
。
显示固定图标
可以在 XAML 中向 Map 添加 Pin
。
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map x:Name="map">
<x:Arguments>
<maps:MapSpan>
<x:Arguments>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
<x:Double>0.01</x:Double>
<x:Double>0.01</x:Double>
</x:Arguments>
</maps:MapSpan>
</x:Arguments>
<maps:Map.Pins>
<maps:Pin Label="Santa Cruz"
Address="The city with a boardwalk"
Type="Place">
<maps:Pin.Location>
<sensors:Location>
<x:Arguments>
<x:Double>36.9628066</x:Double>
<x:Double>-122.0194722</x:Double>
</x:Arguments>
</sensors:Location>
</maps:Pin.Location>
</maps:Pin>
</maps:Map.Pins>
</maps:Map>
</ContentPage>
此 XAML 创建一个 Map 对象,该对象显示由 MapSpan
该对象指定的区域。 该 MapSpan
对象以纬度和经度为中心,Location
对象表示的范围是 0.01 纬度和经度度。
Pin
对象将添加到Map.Pins
集合中,并在其Location
属性指定的位置绘制Map对象。 有关类 Location
的信息,请参阅 位置和距离。 有关将 XAML 中的参数传递给缺少默认构造函数的对象的信息,请参阅 XAML 中的传递参数。
等效的 C# 代码为:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map
{
...
};
Pin pin = new Pin
{
Label = "Santa Cruz",
Address = "The city with a boardwalk",
Type = PinType.Place,
Location = new Location(36.9628066, -122.0194722)
};
map.Pins.Add(pin);
此示例代码导致在地图上呈现单个图钉:
与图钉互动
默认情况下,点击 Pin
时,其信息窗口会显示。
点击地图上的其他地方会关闭信息窗口。
该 Pin
类定义了一个 MarkerClicked
事件,当点击 Pin
时触发。 无需处理此事件以显示信息窗口。 相反,当需要获知特定引脚被点击时,应当处理此事件。
该 Pin
类还定义了 InfoWindowClicked
在点击信息窗口时触发的事件。 当需要通知特定信息窗口已点击时,应处理此事件。
以下代码演示了一个处理这些事件的示例:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Pin boardwalkPin = new Pin
{
Location = new Location(36.9641949, -122.0177232),
Label = "Boardwalk",
Address = "Santa Cruz",
Type = PinType.Place
};
boardwalkPin.MarkerClicked += async (s, args) =>
{
args.HideInfoWindow = true;
string pinName = ((Pin)s).Label;
await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
};
Pin wharfPin = new Pin
{
Location = new Location(36.9571571, -122.0173544),
Label = "Wharf",
Address = "Santa Cruz",
Type = PinType.Place
};
wharfPin.InfoWindowClicked += async (s, args) =>
{
string pinName = ((Pin)s).Label;
await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
};
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Pin boardwalkPin = new Pin
{
Location = new Location(36.9641949, -122.0177232),
Label = "Boardwalk",
Address = "Santa Cruz",
Type = PinType.Place
};
boardwalkPin.MarkerClicked += async (s, args) =>
{
args.HideInfoWindow = true;
string pinName = ((Pin)s).Label;
await DisplayAlertAsync("Pin Clicked", $"{pinName} was clicked.", "Ok");
};
Pin wharfPin = new Pin
{
Location = new Location(36.9571571, -122.0173544),
Label = "Wharf",
Address = "Santa Cruz",
Type = PinType.Place
};
wharfPin.InfoWindowClicked += async (s, args) =>
{
string pinName = ((Pin)s).Label;
await DisplayAlertAsync("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
};
PinClickedEventArgs
这两个事件附带的对象具有一HideInfoWindow
个类型bool
属性。 当此属性设置为 true
事件处理程序内部时,信息窗口将被隐藏。
针类型
Pin
对象包括一个 Type
类型属性,该属性 PinType
表示引脚的类型。
PinType
枚举定义以下成员:
-
Generic
,表示泛型引脚。 -
Place
,表示位置的标记。 -
SavedPin
,表示已保存位置的图钉。 -
SearchResult
,表示搜索结果的标记。
但是,将 Pin.Type
属性设置为任何 PinType
成员不会更改呈现的图钉的外观。 相反,必须自定义 Pin
处理程序以自定义引脚外观。 有关处理程序自定义的详细信息,请参阅 使用处理程序自定义控件。
显示图钉集合
该 Map 类定义以下可绑定属性:
-
ItemsSource
,类型IEnumerable
,指定要显示的固定项的IEnumerable
集合。 -
ItemTemplate
,其类型为 DataTemplate,指定 DataTemplate 应用于显示的引脚集合中的每个项。 -
ItemTemplateSelector
,类型 DataTemplateSelector,指定用于在运行时选择 DataTemplate 引脚的 DataTemplateSelector。
重要
设置属性和ItemTemplateSelector
属性时ItemTemplate
,该ItemTemplate
属性优先。
通过使用数据绑定将Map的ItemsSource
属性绑定到IEnumerable
集合,可以填充图钉。
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps">
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Positions}">
<maps:Map.ItemTemplate>
<DataTemplate x:DataType="models:Position">
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
...
</Grid>
</ContentPage>
属性 ItemsSource
绑定到已连接的视图模型的 Positions
属性,该属性返回一个由 Position
对象组成的 ObservableCollection
,即一种自定义类型。 每个 Position
对象定义 Address
类型和 Description
类型 string
的属性以及 Location
属性 Location
。
通过将属性设置为ItemTemplate
DataTemplate包含Pin
数据绑定到相应属性的对象来定义集合中IEnumerable
每个项的外观。
以下屏幕截图显示了 Map 使用数据绑定显示 Pin
集合:
在运行时选择项外观
IEnumerable
集合中每个项目的外观可以在运行时根据项目值进行选择,方法是将ItemTemplateSelector
属性设置为DataTemplateSelector。
<ContentPage ...
xmlns:templates="clr-namespace:WorkingWithMaps.Templates"
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:viewmodels="clr-namespace:WorkingWithMaps.ViewModels"
x:DataType="viewmodels:PinItemsSourcePageViewModel">
<ContentPage.Resources>
<templates:MapItemTemplateSelector x:Key="MapItemTemplateSelector">
<templates:MapItemTemplateSelector.DefaultTemplate>
<DataTemplate x:DataType="models:Position">
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</templates:MapItemTemplateSelector.DefaultTemplate>
<templates:MapItemTemplateSelector.SanFranTemplate>
<DataTemplate x:DataType="models:Position">
<maps:Pin Location="{Binding Location}"
Address="{Binding Address}"
Label="Xamarin!" />
</DataTemplate>
</templates:MapItemTemplateSelector.SanFranTemplate>
</templates:MapItemTemplateSelector>
</ContentPage.Resources>
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Positions}"
ItemTemplateSelector="{StaticResource MapItemTemplateSelector}">
...
</Grid>
</ContentPage>
以下示例演示了类 MapItemTemplateSelector
:
using WorkingWithMaps.Models;
namespace WorkingWithMaps.Templates;
public class MapItemTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultTemplate { get; set; }
public DataTemplate SanFranTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
return ((Position)item).Address.Contains("San Francisco") ? SanFranTemplate : DefaultTemplate;
}
}
该 MapItemTemplateSelector
类定义 DefaultTemplate
和 SanFranTemplate
DataTemplate 设置为不同数据模板的属性。 该方法OnSelectTemplate
返回SanFranTemplate
,当Pin
被点击且项目地址包含“旧金山”时,显示“Xamarin”作为标签。 当项没有包含“旧金山”的地址时,该方法OnSelectTemplate
将返回 。DefaultTemplate
注释
此功能的用例是基于子类型将子类 Pin
化对象的属性绑定到不同的属性 Pin
。
有关数据模板选择器的详细信息,请参阅 创建 DataTemplateSelector。
多边形、折线和圆圈
Polygon
和Polyline
Circle
元素允许你在地图上突出显示特定区域。 A Polygon
是一个完全封闭的形状,可以有描边和填充颜色。 A Polyline
是一条未完全封闭区域的线条。 地图上的圆形区域由Circle
突出显示。
Polygon
、Polyline
和Circle
类派生自MapElement
类,该类公开以下可绑定属性:
-
StrokeColor
是一个 Color 确定线条颜色的对象。 -
StrokeWidth
是一个float
确定线条宽度的对象。
该 Polygon
类定义其他可绑定属性:
-
FillColor
是一个 Color 确定多边形背景色的对象。
此外,Polygon
类和Polyline
类分别定义了一个GeoPath
属性,该属性是由Location
对象组成的一个列表,这些对象指定了形状的点。
该 Circle
类定义以下可绑定属性:
-
Center
是一个Location
对象,用于定义圆的中心(以纬度和经度为单位)。 -
Radius
是一个Distance
对象,用于定义圆的半径(以米、公里或英里为单位)。 -
FillColor
是一个 Color 属性,用于确定圆周内的颜色。
创建多边形
可以通过实例化Polygon
对象并将其添加到地图的MapElements
集合中来将对象添加到地图中。
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Polygon StrokeColor="#FF9900"
StrokeWidth="8"
FillColor="#88FF9900">
<maps:Polygon.Geopath>
<sensors:Location>
<x:Arguments>
<x:Double>47.6458676</x:Double>
<x:Double>-122.1356007</x:Double>
</x:Arguments>
</sensors:Location>
<sensors:Location>
<x:Arguments>
<x:Double>47.6458097</x:Double>
<x:Double>-122.142789</x:Double>
</x:Arguments>
</sensors:Location>
...
</maps:Polygon.Geopath>
</maps:Polygon>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
等效的 C# 代码为:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map();
// Instantiate a polygon
Polygon polygon = new Polygon
{
StrokeWidth = 8,
StrokeColor = Color.FromArgb("#1BA1E2"),
FillColor = Color.FromArgb("#881BA1E2"),
Geopath =
{
new Location(47.6368678, -122.137305),
new Location(47.6368894, -122.134655),
...
}
};
// Add the polygon to the map's MapElements collection
map.MapElements.Add(polygon);
StrokeColor
和StrokeWidth
属性被指定用于设置多边形的轮廓。 在此示例中,FillColor
属性值与 StrokeColor
属性值匹配,但由于指定了 alpha 值,使其具有透明效果,从而允许基础地图在形状中可见。 该 GeoPath
属性包含定义多边形点地理坐标的对象列表 Location
。 对象Polygon
添加到Map的集合MapElements
后,该对象将在地图上被渲染。
注释
A Polygon
是一个完全封闭的形状。 如果第一个点和最后一个点不匹配,将自动连接。
创建折线
Polyline
对象可以通过实例化并添加到地图的MapElements
集合中来添加。
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Polyline StrokeColor="Black"
StrokeWidth="12">
<maps:Polyline.Geopath>
<sensors:Location>
<x:Arguments>
<x:Double>47.6381401</x:Double>
<x:Double>-122.1317367</x:Double>
</x:Arguments>
</sensors:Location>
<sensors:Location>
<x:Arguments>
<x:Double>47.6381473</x:Double>
<x:Double>-122.1350841</x:Double>
</x:Arguments>
</sensors:Location>
...
</maps:Polyline.Geopath>
</maps:Polyline>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
等效的 C# 代码为:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
...
Map map = new Map();
// instantiate a polyline
Polyline polyline = new Polyline
{
StrokeColor = Colors.Blue,
StrokeWidth = 12,
Geopath =
{
new Location(47.6381401, -122.1317367),
new Location(47.6381473, -122.1350841),
...
}
};
// Add the Polyline to the map's MapElements collection
map.MapElements.Add(polyline);
定义 StrokeColor
属性和 StrokeWidth
属性以设置线条外观。 该 GeoPath
属性包含定义折线点地理坐标的对象列表 Location
。
Polyline
一旦对象被添加到该对象的集合Map,对象就会在地图上MapElements
呈现。
创建圆形
可以通过实例化Circle
对象,然后将其添加到地图的MapElements
集合中。
<ContentPage ...
xmlns:maps="http://schemas.microsoft.com/dotnet/2021/maui/maps"
xmlns:sensors="clr-namespace:Microsoft.Maui.Devices.Sensors;assembly=Microsoft.Maui.Essentials">
<maps:Map>
<maps:Map.MapElements>
<maps:Circle StrokeColor="#88FF0000"
StrokeWidth="8"
FillColor="#88FFC0CB">
<maps:Circle.Center>
<sensors:Location>
<x:Arguments>
<x:Double>37.79752</x:Double>
<x:Double>-122.40183</x:Double>
</x:Arguments>
</sensors:Location>
</maps:Circle.Center>
<maps:Circle.Radius>
<maps:Distance>
<x:Arguments>
<x:Double>250</x:Double>
</x:Arguments>
</maps:Distance>
</maps:Circle.Radius>
</maps:Circle>
</maps:Map.MapElements>
</maps:Map>
</ContentPage>
等效的 C# 代码为:
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Maps;
using Map = Microsoft.Maui.Controls.Maps.Map;
Map map = new Map();
// Instantiate a Circle
Circle circle = new Circle
{
Center = new Location(37.79752, -122.40183),
Radius = new Distance(250),
StrokeColor = Color.FromArgb("#88FF0000"),
StrokeWidth = 8,
FillColor = Color.FromArgb("#88FFC0CB")
};
// Add the Circle to the map's MapElements collection
map.MapElements.Add(circle);
地图上的Circle
位置取决于Center
和Radius
属性的值。 该 Center
属性定义圆的中心(以纬度和经度为单位),而 Radius
该属性以米为单位定义圆的半径。 指定 StrokeColor
属性 StrokeWidth
以设置圆的轮廓。
FillColor
属性值指定圆周内的颜色。 在此示例中,这两个颜色值都指定 alpha 通道,从而允许通过圆圈显示基础地图。 一旦对象被添加到MapElements
Map集合中,该Circle
对象就会在地图上呈现。
注释
该GeographyUtils
类具有一个ToCircumferencePositions
扩展方法,该方法将Circle
对象(定义Center
和Radius
属性值)转换为一个对象列表,这些对象构成圆周的纬度和经度坐标Location
。
地理编码和地理位置
命名空间 Microsoft.Maui.Devices.Sensors
中的 Geocoding
类可用于将地标地理编码为定位坐标,并将坐标反向地理编码为地标。 有关详细信息,请参阅 Geocoding。
命名空间 Geolocation
中的 Microsoft.Maui.Devices.Sensors
类可用于检索设备的当前地理位置坐标。 有关详细信息,请参阅 地理位置。
启动本机地图应用
每个平台上的原生地图应用可以通过 Launcher
类从 .NET MAUI 应用程序启动。 此类使应用能够通过其自定义 URI 方案打开另一个应用。 可以使用方法调用 OpenAsync
启动器功能,传入 string
表示要打开的自定义 URL 方案的参数 Uri
。 有关该 Launcher
类的详细信息,请参阅 Launcher。
每个平台上的地图应用都使用唯一的自定义 URI 方案。 有关 iOS 上的映射 URI 方案的信息,请参阅 developer.apple.com 上的 地图链接 。 有关 Android 上的地图 URI 方案的信息,请参阅 developers.android.com 上的 Android 地图开发人员指南 和 Google Maps 意向 。 有关 Windows 上的地图 URI 方案的信息,请参阅 “启动 Windows 地图”应用。
在特定位置启动地图应用
通过将相应的查询参数添加到每个地图应用的自定义 URI 方案,可以打开本机地图应用中的位置:
if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
{
// https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
await Launcher.OpenAsync("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
// opens the Maps app directly
await Launcher.OpenAsync("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
{
await Launcher.OpenAsync("bingmaps:?where=394 Pacific Ave San Francisco CA");
}
此示例代码导致在每个平台上启动本机地图应用,地图以表示指定位置的图钉为中心。
打开地图应用并生成路线
通过将相应的查询参数添加到每个地图应用的自定义 URI 方案,可以启动本机地图应用显示方向:
if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
{
// https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
await Launcher.OpenAsync("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
{
// opens the 'task chooser' so the user can pick Maps, Chrome or other mapping app
await Launcher.OpenAsync("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View");
}
else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
{
await Launcher.OpenAsync("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052");
}
此示例代码导致在每个平台上启动本机地图应用,地图以指定位置之间的路线为中心。