刷新谷歌地图中的针脚位置

时间:2018-01-23 07:34:48

标签: google-maps xamarin location refresh google-maps-markers

我有一个跨平台应用程序,其中包含一些显示车辆位置的引脚。

我想要做的就是在车辆移动时刷新车辆位置,就像gps在我们自己的位置一样。

将来,我从一个不断实现的数据库中收到位置数据。目前,由于我还没有任何数据库,我手动设置位置值。

有任何想法如何刷新引脚位置并在地图上显示新位置吗?

我发布了我的地图代码,希望它有所帮助。

public partial class MapPage : ContentPage
{
    public static int ScreenHeight { get; set; }
    public static int ScreenWidth { get; set; }

    Plugin.Geolocator.Abstractions.Position position;

    Map map;
    public MapPage()
    {
        Title = "Mapa";
        map = new Map
        {
            IsShowingUser = true,
            HeightRequest = Height, //ScreenHeight,
            WidthRequest = Width, //ScreenWidth,
            VerticalOptions = LayoutOptions.FillAndExpand                
        };

        ArrayList listaPines = loadPines();

        for(int i = 0; i < listaPines.Count; i++)
            map.Pins.Add((Pin)listaPines[i]);

        // Añadir el slider  
        var slider = new Slider(1, 18, 1);
        slider.ValueChanged += (sender, e) => {
            var zoomLevel = e.NewValue; // entre 1 y 18  
            var latlongdegrees = 360 / (Math.Pow(2, zoomLevel));
            Debug.WriteLine(zoomLevel + " -> " + latlongdegrees);
            if (map.VisibleRegion != null) map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongdegrees, latlongdegrees));
        };

        // Botones de mapa  
        var street = new Button
        {
            Text = "Calle"                
        };
        var hybrid = new Button
        {
            Text = "Hibrido"
        };
        var satellite = new Button
        {
            Text = "Satelite"
        };
        street.Clicked += HandleClicked;
        hybrid.Clicked += HandleClicked;
        satellite.Clicked += HandleClicked;
        var segments = new StackLayout
        {
            Spacing = 1,
            HorizontalOptions = LayoutOptions.FillAndExpand,
            Orientation = StackOrientation.Horizontal,
            Children = {
                        street,
                        hybrid,
                        satellite
            }
        };

        Pin pin1 = (Pin)listaPines[0];
        Pin pin2 = (Pin)listaPines[1];

        double distancia = distance(pin1.Position.Latitude, pin1.Position.Longitude, pin2.Position.Latitude, pin2.Position.Longitude, 'K');
        var distancias = new Label
        {
            Text = "Distancia entre puntos V1 y V2: " + Math.Round(distancia, 3) +" km."
        };

        // Añadir complementos (mapa, slider y botones)  
        var stack = new StackLayout
        {
            Spacing = 0
        };
        stack.Children.Add(map);
        stack.Children.Add(slider);
        stack.Children.Add(segments);
        stack.Children.Add(distancias);
        Content = stack;

        // Para debug
        map.PropertyChanged += (sender, e) => {
            Debug.WriteLine(e.PropertyName + " just changed!");
            if (e.PropertyName == "VisibleRegion" && map.VisibleRegion != null) CalculateBoundingCoordinates(map.VisibleRegion);
        };
    }

    /// <summary>
    /// Método para cargar el listado de pines aleatorio
    /// </summary>
    /// <returns></returns>
    private ArrayList loadPines()
    {
        ArrayList listaPines = new ArrayList();

        Pin myPin = new Pin();
        for (int i = 0; i < 5; i++)
        {
            var position = new Position(42.4653488 + i, -4.919838700000014 + i);
            var pin = new Pin
            {
                Type = PinType.Place,
                Position = position,
                Label = "V " + i.ToString(),
                Address = "Direccion " + i.ToString()
            };
            listaPines.Add(pin);
        }

        return listaPines;
    }

    /// <summary>
    /// Método para calcular la distancia entre dos puntos
    /// </summary>
    /// <param name="lat1">Latitud del primer punto</param>
    /// <param name="lon1">Longitud del primer punto</param>
    /// <param name="lat2">Latitud del segundo punto</param>
    /// <param name="lon2">Longitud del segundo punto</param>
    /// <param name="unit">Unidades - M: millas (por defecto, sin conversión), K: kilómetros, N: millas naúticas</param>
    /// <returns></returns>
    private double distance(double lat1, double lon1, double lat2, double lon2, char unit)
    {
        double theta = lon1 - lon2;
        double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
        dist = Math.Acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60 * 1.1515;
        if (unit == 'K')
        {
            dist = dist * 1.609344;
        }
        else if (unit == 'N')
        {
            dist = dist * 0.8684;
        }
        return (dist);
    }

    /// <summary>
    /// Método para convertir de grados sexagesimales a radianes
    /// </summary>
    /// <param name="deg">Grados sexagesimales</param>
    /// <returns></returns>
    private double deg2rad(double deg)
    {
        return (deg * Math.PI / 180.0);
    }

    /// <summary>
    /// Método para convertir de radianes a grados sexagesimales
    /// </summary>
    /// <param name="rad">Radianes</param>
    /// <returns></returns>
    private double rad2deg(double rad)
    {
        return (rad / Math.PI * 180.0);
    }

    /// <summary>
    /// Método asíncrono para obtener la posición del GPS
    /// </summary>
    protected async override void OnAppearing()
    {
        //Posible if a quitar
        if (CrossGeolocator.Current.IsGeolocationAvailable)
        {
            position = await GetPosition();

            map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromMiles(0.3)));
        }
    }

    /// <summary>
    /// Tarea asíncrona que devuelve la posición del GPS
    /// </summary>
    /// <returns></returns>
    async Task<Plugin.Geolocator.Abstractions.Position> GetPosition()
    {
        var locator = CrossGeolocator.Current;
        locator.DesiredAccuracy = 50;

        Plugin.Geolocator.Abstractions.Position position = await locator.GetPositionAsync(TimeSpan.FromSeconds(5));

        return position;
    }

    /// <summary>
    /// Evento para gestionar los clicks en los botones inferiores
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void HandleClicked(object sender, EventArgs e)
    {
        var b = sender as Button;
        switch (b.Text)
        {
            case "Calle":
                map.MapType = MapType.Street;
                break;
            case "Hibrido":
                map.MapType = MapType.Hybrid;
                break;
            case "Satelite":
                map.MapType = MapType.Satellite;
                break;
        }
    }

    /// <summary>  
    /// In response to this forum question http://forums.xamarin.com/discussion/22493/maps-visibleregion-bounds  
    /// Useful if you need to send the bounds to a web service or otherwise calculate what  
    /// pins might need to be drawn inside the currently visible viewport.  
    /// </summary>  
    static void CalculateBoundingCoordinates(MapSpan region)
    {
        // WARNING: I haven't tested the correctness of this exhaustively!  
        var center = region.Center;
        var halfheightDegrees = region.LatitudeDegrees / 2;
        var halfwidthDegrees = region.LongitudeDegrees / 2;
        var left = center.Longitude - halfwidthDegrees;
        var right = center.Longitude + halfwidthDegrees;
        var top = center.Latitude + halfheightDegrees;
        var bottom = center.Latitude - halfheightDegrees;
        // Adjust for Internation Date Line (+/- 180 degrees longitude)  
        if (left < -180) left = 180 + (180 + left);
        if (right > 180) right = (right - 180) - 180;
        // I don't wrap around north or south; I don't think the map control allows this anyway  
        Debug.WriteLine("Bounding box:");
        Debug.WriteLine(" " + top);
        Debug.WriteLine(" " + left + " " + right);
        Debug.WriteLine(" " + bottom);
    }
}

谢谢! :)

1 个答案:

答案 0 :(得分:0)

我使用这个计时器功能/事件来解决它:

private bool TimerCallBack()
{
    listaPines = loadPines(valores);
    valores++;
    map.Pins.Clear();
    cargarPinesEnMapa();

    return true;
}

方法cargarPinesEnMapa:

private void cargarPinesEnMapa()
{
    for (int i = 0; i < listaPines.Count; i++)
        map.Pins.Add((Pin)listaPines[i]);
}

因此,它每两秒更改一次值,并重新加载地图上的引脚位置。