我有一个跨平台应用程序,其中包含一些显示车辆位置的引脚。
我想要做的就是在车辆移动时刷新车辆位置,就像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);
}
}
谢谢! :)
答案 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]);
}
因此,它每两秒更改一次值,并重新加载地图上的引脚位置。