Xamarin Forms Maps-如何刷新/更新地图-CustomMap Renderer [英] Xamarin Forms Maps - how to refresh/update the map - CustomMap Renderer

查看:90
本文介绍了Xamarin Forms Maps-如何刷新/更新地图-CustomMap Renderer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我搜索了很多,但仍然遇到相同的问题:

I search a lot but I still have the same problem:

如何更新,刷新或重新加载Xamarin.Forms.Maps?

在类定义(CustomMap:地图)中,没有更新地图的方法.也许MVVM逻辑可以解决问题,但我无法在Web上找到它..

In the class definition (class CustomMap : Map), there is no method to update the maps.. Maybe a MVVM logic can solves the problem, but I can't find it on the Web..

我按照本教程学习了地图:使用地图

I followed this tutorial for the maps : Working with maps

要对其进行自定义,我遵循了本教程:

To customise it, I followed this tutorial : Highlight a Route on a Map

因此,在完成这些教程(我做了同样的事情,没有做任何更改)之后,我尝试使用2个RouteCoordinates,这给了我一条直线...然后我制定了一种算法,可以完美地工作.

So, after these tutorials (I made the same things, no changes), I tried with 2 RouteCoordinates which gave me a straight line... I then made an algorithm which works perfectly.

DirectionMap

public class DirectionMap
{
    public Distance distance { get; set; }
    public Duration duration { get; set; }
    public Address address_start { get; set; }
    public Address address_end { get; set; }
    public List<Step> steps { get; set; }

    public class Distance
    {
        public string text { get; set; }
        public int value { get; set; }
    }
    public class Duration
    {
        public string text { get; set; }
        public int value { get; set; }
    }
    public class Address
    {
        public string text { get; set; }
        public Position position { get; set; }
    }
    public class Step
    {
        public Position start { get; set; }
        public Position end { get; set; }
    }
}

ResponseHttpParser

public static void parseDirectionGoogleMapsResponse(HttpStatusCode httpStatusCode, JObject json, Action<DirectionMap, string> callback)
{
    switch (httpStatusCode)
    {
        case HttpStatusCode.OK:

            DirectionMap directionMap = null;
            string strException = null;

            try
            {
                directionMap = new DirectionMap()
                {
                    distance = new DirectionMap.Distance()
                    {
                        text = (json["routes"][0]["legs"][0]["distance"]["text"]).ToString(),
                        value = Int32.Parse((json["routes"][0]["legs"][0]["distance"]["value"]).ToString())
                    },
                    duration = new DirectionMap.Duration()
                    {
                        text = (json["routes"][0]["legs"][0]["duration"]["text"]).ToString(),
                        value = Int32.Parse((json["routes"][0]["legs"][0]["duration"]["value"]).ToString())
                    },
                    address_start = new DirectionMap.Address()
                    {
                        text = (json["routes"][0]["legs"][0]["start_address"]).ToString(),
                        position = new Position(Double.Parse((json["routes"][0]["legs"][0]["start_location"]["lat"]).ToString()), Double.Parse((json["routes"][0]["legs"][0]["start_location"]["lng"]).ToString()))
                    },
                    address_end = new DirectionMap.Address()
                    {
                        text = (json["routes"][0]["legs"][0]["end_address"]).ToString(),
                        position = new Position(Double.Parse((json["routes"][0]["legs"][0]["end_location"]["lat"]).ToString()), Double.Parse((json["routes"][0]["legs"][0]["end_location"]["lng"]).ToString()))
                    }
                };

                bool finished = false;
                directionMap.steps = new List<Step>();
                int index = 0;

                while (!finished)
                {
                    try
                    {
                        Step step = new Step()
                        {
                            start = new Position(Double.Parse((json["routes"][0]["legs"][0]["steps"][index]["start_location"]["lat"]).ToString()), Double.Parse((json["routes"][0]["legs"][0]["steps"][index]["start_location"]["lng"]).ToString())),
                            end = new Position(Double.Parse((json["routes"][0]["legs"][0]["steps"][index]["end_location"]["lat"]).ToString()), Double.Parse((json["routes"][0]["legs"][0]["steps"][index]["end_location"]["lng"]).ToString()))
                        };
                        directionMap.steps.Add(step);
                        index++;
                    }
                    catch (Exception e)
                    {
                        finished = true;
                    }
                }
            }
            catch (Exception e)
            {
                directionMap = null;
                strException = e.ToString();
            }
            finally
            {
                callback(directionMap, strException);
            }
            break;
        default:
            switch (httpStatusCode)
            {

            }
            callback(null, json.ToString());
            break;
    }
}

我只是获得一些私人计算的距离和持续时间,并获得我放入列表中的每一步>

I just get the distance and duration for some private calculs and get each step that I put into a List<>;

一切完成后,我使用回调将我们带回到控制器(XAML表单页面(Xamarin Portable)MapPage.xaml.cs)

When everything is finished, I use my callback which bring us back to the controller (MapPage.xaml.cs the XAML Form Page (Xamarin Portable))

现在,一切都变得怪异了.就像地图没有更改一样

Now, everything becomes weird. It's like the map doesn't get that changes are made

public partial class MapPage : ContentPage
{
    public MapPage()
    {
        InitializeComponent();
        setupMap();
        setupMapCustom();
    }

    public void setupMapCustom()
    {
        customMap.RouteCoordinates.Add(new Position(37.785559, -122.396728));
        customMap.RouteCoordinates.Add(new Position(37.780624, -122.390541));
        customMap.RouteCoordinates.Add(new Position(37.777113, -122.394983));
        customMap.RouteCoordinates.Add(new Position(37.776831, -122.394627));

        customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Xamarin.Forms.Maps.Distance.FromMiles(1.0)));
    }       

    public async void setupMap()
    {
        customMap.MapType = MapType.Satellite;

        string origin = "72100 Le Mans";
        string destination = "75000 Paris";

        HttpRequest.getDirections(origin, destination, callbackDirections);

        customMap.RouteCoordinates.Add(await MapUtilities.GetMapPointOfStreetAddress(origin));
        Position position = await MapUtilities.GetMapPointOfStreetAddress(destination);
        //customMap.RouteCoordinates.Add(position);

        var pin = new Pin
        {
            Type = PinType.Place,
            Position = position,
            Label = "Destination !!",
        };
        customMap.Pins.Add(pin);
    }

    private async void callbackDirections(Object obj, string str)
    {
        if (obj != null)
        {
            DirectionMap directionMap = obj as DirectionMap;

            foreach (Step step in directionMap.steps)
            {
                customMap.RouteCoordinates.Add(step.start);
                System.Diagnostics.Debug.WriteLine("add step");
            }

            customMap.RouteCoordinates.Add(directionMap.address_end.position);
            System.Diagnostics.Debug.WriteLine("add last step");
        }
        else
        {
            System.Diagnostics.Debug.WriteLine(str);
        }
    }
}

我运行我的应用程序,一切正常,直到它变得很快,因为我的算法等花费了时间,回调来得太晚了,然后我需要刷新、重新加载或更新我的地图......无论如何,我需要以后再更新我的地图,所以...如果有人可以提供帮助,欢迎您!

I run my app, everything works until it's something fast, because of the time spent by my algorithm etc, the callback is coming too late and then I need to refresh, reload or update my map... Anyway, I need to update my map in the future, so... If anyone can help, this one is welcome !

编辑1 我看了看你的回答(非常感谢!;)),但是它不起作用:/

EDIT 1 I took a look at your answer ( thank a lot ! ;) ) but it doesn't works :/

我像您一样更新了 CustomMap

public class CustomMap : Map
{
    public static readonly BindableProperty RouteCoordinatesProperty =
    BindableProperty.Create<CustomMap, List<Position>>(p => p.RouteCoordinates, new List<Position>());

    public List<Position> RouteCoordinates
    {
        get { return (List<Position>)GetValue(RouteCoordinatesProperty); }
        set { SetValue(RouteCoordinatesProperty, value); }
    }

    public CustomMap()
    {
        RouteCoordinates = new List<Position>();
    }
}

CustomMapRenderer(Droid)

public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
    GoogleMap map;
    Polyline polyline;

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            // Unsubscribe
        }

        if (e.NewElement != null)
        {
            ((MapView)Control).GetMapAsync(this);
        }
    }

    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        base.OnElementPropertyChanged(sender, e);
        if (this.Element == null || this.Control == null)
            return;

        if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
        {
            UpdatePolyLine();
        }
    }

    private void UpdatePolyLine()
    {
        if (polyline != null)
        {
            polyline.Remove();
            polyline.Dispose();
        }

        var polylineOptions = new PolylineOptions();
        polylineOptions.InvokeColor(0x66FF0000);

        foreach (var position in ((CustomMap)this.Element).RouteCoordinates)
        {
            polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
        }

        polyline = map.AddPolyline(polylineOptions);
    }

    public void OnMapReady(GoogleMap googleMap)
    {
        map = googleMap;
        UpdatePolyLine();
    }
}

因此,对于最后一次更改,在您的MapPage.xaml.cs中,我按照您的说明对callbackDirections进行了更改(希望我做得很好)

So, for the last change, in my MapPage.xaml.cs I made changes in the callbackDirections as you explained (I hope I did good)

private async void callbackDirections(Object obj, string str)
    {
        if (obj != null)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                DirectionMap directionMap = obj as DirectionMap;
                var list = new List<Position>(customMap.RouteCoordinates);

                foreach (Step step in directionMap.steps)
                {
                    list.Add(directionMap.address_end.position);
                    System.Diagnostics.Debug.WriteLine("add step");
                }

                System.Diagnostics.Debug.WriteLine("last step");
                customMap.RouteCoordinates = list;
                System.Diagnostics.Debug.WriteLine("finished?");
            });
        }
        else
        {
            System.Diagnostics.Debug.WriteLine(str);
        }
    }

地图仍然没有显示折线:/我只是进行了这些更改,没有对我之前的代码进行任何其他更改.

The map is still doesn't display the polyline :/ I only made these changes, I didn't change anything else from my previous code.

我没有告诉你,但是我不是MVVM绑定专家,所以如果我忘记了什么,对不起:/

I didn't tell you, but I'm not an expert in MVVM binding, so if I forget something, I'm sorry :/

编辑2 因此,在您回答了问题并进行了一些阅读,阅读和重新阅读后,MapPage.xaml.cs中就有了我的测试代码"

EDIT 2 So after your answer and some read, read and re-read of your answer, there is my "test code" in MapPage.xaml.cs

public MapPage()
    {
        InitializeComponent();
        //HttpRequest.getDirections(origin, destination, callbackDirections);

        Device.BeginInvokeOnMainThread(() =>
        {
            customMap.RouteCoordinates = new List<Position>
            {
                new Position (37.797534, -122.401827),
                new Position (37.776831, -122.394627)
            };
        });

        //setupMap();
        //setupMapCustom();
    }

因为它对我不起作用,所以我看了一下我的代码,然后,我看到 public static readonly BindableProperty RouteCoordinatesProperty =BindableProperty.Create< CustomMap,List< Position>>(p =>p.RouteCoordinates,不推荐使用新的List< Position>()); .

Because it doesn't works (for me), I took a look at my code and then, I saw that public static readonly BindableProperty RouteCoordinatesProperty = BindableProperty.Create<CustomMap, List<Position>>( p => p.RouteCoordinates, new List<Position>()); was deprecated..

所以我对这个发布以另一种方式实现此绑定,但它也表示不建议使用此方式在这里 ...我还看到了一些有关绑定的教程,其中说他们在xaml中放入了一些代码,让我记得你是我的

So I red on this post a different way to implement this binding, but it also said that this way is deprecated SEE HERE... I also saw some tutorials about binding which says that they put some code into their xaml, let me remember you mine

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:local="clr-namespace:NAMESPACE;assembly=NAMESPACE"
     x:Class="NAMESPACE.Controlers.MapPage">
         <ContentPage.Content>
             <local:CustomMap x:Name="customMap"/>
         </ContentPage.Content>
</ContentPage>

我没有使用某些东西作为ItemSource ="{PolylineBindable}"

I'm not using something as ItemSource="{PolylineBindable}"

推荐答案

因此,经过大量搜索,当然还有@ Sven-MichaelStübe的回答,您可以拥有可以在每个平台上使用的适当地图,"Android,iOS、WinPhone".遵循我的代码,然后按照@ Sven-MichaelStübe的回答对其进行编辑.

So after lot of searches and, of course, the answer of @Sven-Michael Stübe, you can have your proper maps which works on each platform "Android, iOS, WinPhone". Follow my code, then edit it following the @Sven-Michael Stübe's answer.

一旦您完成所有操作,它就可以工作(例如@ Sven-MichaelStübe),但也不能工作(例如对我来说).如果不起作用,请尝试更改以下代码:

Once you finished everything, it could works (like for @Sven-Michael Stübe), but it also couldn't work (like for me). If it doesn't works, try to change the following code:

public static readonly BindableProperty RouteCoordinatesProperty =
    BindableProperty.Create<CustomMap, List<Position>>(
        p => p.RouteCoordinates, new List<Position>());

作者

public static readonly BindableProperty RouteCoordinatesProperty =
    BindableProperty.Create(nameof(RouteCoordinates), typeof(List<Position>), typeof(CustomMap), new List<Position>(), BindingMode.TwoWay);

然后代码起作用!

PS:您可能会对折线产生一些麻烦,但我没有在正确的道路上进行.

PS: You can have some troubles with the polyline at the end, which not following the road right, I'm working on it.

PS2:我还将制作一个视频,解释如何对customMap进行编码,而不必安装NuGet包,以便最终可以编辑所有内容!(第一个使用法语,第二个使用英语,在制作视频后将对此帖子进行编辑)

PS2: I'll also make a video to explain how to code your customMap to don't have to install a NuGet package, to be able to edit everything at the end ! (The first one will be in French, the second in English, this post will be edited when the video will be made)

再次感谢@ Sven-MichaelStübe!也感谢他的回答:)

Thank angain to @Sven-Michael Stübe !! Thank to up his answer as well :)

这篇关于Xamarin Forms Maps-如何刷新/更新地图-CustomMap Renderer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆