在您的Xamarin表格应用中使用地址,地图和地形等

00_titleimage.

曾经不得不开发一个应用程序的位置感兴趣的应用程序。用户,商店,餐厅或其他景点的地址?直线版本可能是向用户提供简单的形式。

地址条目表格

虽然表格易于实施和可靠,但它可能很麻烦。另外,如果您想导航到该位置,该呢?或者为什么不使用设备的位置?点击地图上获取地址?好吧,所有这些东西都可以很容易地通过Xamarin团队提供的一些有用的图书馆来实现。

像Pro的地理编码

每当您需要在坐标和地址之间转换时, 地理编码 是你最好的朋友。您可以显示出地址或位置,您将返回相反:

var location = (await Geocoding.GetLocationsAsync($"{street}, {city}, {country}")).FirstOrDefault();

if (location == null) return;

Position = new Position(location.Latitude, location.Longitude);

因此,如果我们有一个用户可以进入地址的形式,我们希望导航到该位置,我们可以将地址转换为Geo坐标,然后使用 Xamarin Essentials.,打开平台上的地图应用程序并导航到该位置。

var location = new Location(Position.Latitude, Position.Longitude);
var options = new MapLaunchOptions { NavigationMode = NavigationMode.Driving };
await Xamarin.Essentials.Map.OpenAsync(location, options);

对一堆条目和几行代码令人印象深刻?

通过一个水龙头获取地址

但在地址中打字可能是麻烦的。为什么不仅选择地图上的位置并从该位置获取地址? XAMARIN表单支持地图控制了很长一段时间。一旦你添加了 尼古特包,它将允许您呈现本机地图平台,即Android上的Google地图。

<?xml version="1.0" encoding="utf-8" ?>
             ...
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
             ... >

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <maps:Map x:Name="MapControl" />
        ...
    </Grid>

</ContentPage>

注意根据您打算的平台需要一些设置步骤。因此,请务必查看Microsoft的官方文档。在这里,我们将继续关注有趣的东西

The map has an event MapClicked which fires when the user taps on the map with the geo-position.

Observable.FromEventPattern<MapClickedEventArgs>(
    mc => MapControl.MapClicked += mc, 
    mc => MapControl.MapClicked -= mc)
    .Subscribe(ev => ViewModel.ExecuteSetAddress.Execute(ev.EventArgs.Position));

如果您不熟悉Rx.Net,则此处是具有事件处理程序的等效代码:

protected override void OnAppearing()
{
   // ...

    MapControl.MapClicked += HandleMapClicked;
}

private void HandleMapClicked(object sender, MapClickedEventArgs e)
{
    var postion = e.Position;
    // ...
}

要为用户提供一些反馈,我们甚至可以用PIN介绍录音位置:

private Unit SetPin(Position position)
{
    Pin pin = new Pin
    {
        Label = "The Place",
        Address = $"{ViewModel.Street}, {ViewModel.City}, {ViewModel.Country}",
        Type = PinType.Place,
        Position = position
    };

    var latDegrees = MapControl.VisibleRegion?.LatitudeDegrees ?? 0.01;
    var longDegrees = MapControl.VisibleRegion?.LongitudeDegrees ?? 0.01;
    MapControl.MoveToRegion(new MapSpan(position, latDegrees, longDegrees));
    MapControl?.Pins?.Clear();
    MapControl?.Pins?.Add(pin);
    return Unit.Default;
}

此代码将始终将PIN放置在新位置。如果用户点击引脚,它将显示提供给PIN的信息。

侧面注意:管理介绍此代码的信息是非常挑战,其中9次,我只设法将PIN放在一个新位置。但也许这只是我

使用Geocoder,我们现在可以获得这些坐标的地址:

private async Task SetAddress(Position p)
{
    var addrs = (await Geocoding.GetPlacemarksAsync(new Location(p.Latitude, p.Longitude))).FirstOrDefault();
    Street = $"{addrs.Thoroughfare} {addrs.SubThoroughfare}";
    City = $"{addrs.PostalCode} {addrs.Locality}";
    Country = addrs.CountryName;
    // ...
}

但现在你有它,从坐标到地址并反过来。很容易吗?嗯,还有一件事;地图指向罗马的默认坐标。我得到它。罗马有很多东西可以提供,但如果您的用户目前尚未在罗马,则在地图有用之前,它可能会有很多捏和滑动。这么长的故事短,为什么不使用用户的位置?

马可?马球!

让用户职位再次成为一块蛋糕,感谢 Xamarin Essentials.。即一旦您需要如下所述的所有权限 关联。只需几行我们可以获得地址并设置位置:

try
{
    var location = await Geolocation.GetLastKnownLocationAsync()var position = new Position(location.Latitude, location.Longitude);Position = position;// ... set address and stuff
}
// many exception handlers according to docs here

如果他们希望共享其位置,请在第一次运行此代码时提示用户提示。就像一个侧面注意如果您不想使用权限对话框扼杀BATT的用户权限,您可能希望在首先运行此代码时会进行一些思考。

因此,当视图出现时,我们可以尝试获取用户的位置并告诉地图控制世界的哪个部分显示:

Geolocation.GetLastKnownLocationAsync()
            .ToObservable()
            .Catch(Observable.Return(new Location()))
            .SubscribeOn(RxApp.MainThreadScheduler)
            .Subscribe(async location => { 
                var position = new Position(location.Latitude, location.Longitude);
                Position = position;
                await SetAddress(position);
            });

我希望你能看到它没有太多的厌倦形式到“有趣”地图控制。

gifrecordingsmall.

并且所有通过使用Microsoft提供给您的标准库。您可以找到完整的样本 GitHub..

Hth.

Updated: