How can I refresh google map programmatically after using animateCamera()? - google-maps

newPosition = new CameraPosition(new LatLng(latitude, longitude), zoomLevel, tilt, currentBearing);
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(newPosition);
googleMap.animateCamera(cameraUpdate);
When I zoom in or move the camera to another point using animateCamera(), it takes a long time for it to refresh the map (it looks blurry). But if I tap the screen or slightly move the camera manually after animation ends, it immediately refreshes.
it looks like this after moving the camera
I want it to refresh and look like this after animation
I searched it in google maps documents but I didn't find a method for refreshing the map. Is there a way to refresh it programmatically?

I fixed this by calling moveCamera() when the animation ends. I am moving the camera to the same location just to make google maps load the map immediately. Couldn't find a better way.
CameraPosition newPosition = newCameraPosition(newLatLng(latitude,longitude), zoomLevel, tilt, currentBearing);
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(newPosition);
googleMap.animateCamera(cameraUpdate, new GoogleMap.CancelableCallback() {
#Override public void onCancel() {}
#Override
public void onFinish() {
googleMap.moveCamera(cameraUpdate);
}
});

Related

Xamarin Android Google Map - Add marker where user clicks

In Xamarin Forms, I am using a custom renderer in Android for a map I have implemented using Android.Gms.Maps I want to write functionality that adds a marker in the area a user clicked on the map.
public async void OnMapReady(GoogleMap googleMap)
{
map.MapClick+= HandleMapClick;
}
In my HandleMapClick() function, how do I use the addMarker() function to add a marker to the area which a user clicked on the map?
The GoogleMap.MapClickEventArgs contains a "Point" that contains the lat/long of the user' click. Create a MarkerOption, assign it that point and add it to your map.
googleMap.MapClick += (object sender, GoogleMap.MapClickEventArgs e) =>
{
using (var markerOption = new MarkerOptions())
{
markerOption.SetPosition(e.Point);
markerOption.SetTitle("StackOverflow");
// save the "marker" variable returned if you need move, delete, update it, etc...
var marker = googleMap.AddMarker(markerOption);
}
};

How to show the path and distance on Google Map - Xamarin

I have a page(fragment) that shows google maps together with 1 marker icon. So now i would like to pass source and destination coordinates to this map so that it can show the shortest route together with the distance in Km. E.g i want the map to show the blue path in the image below :
Here is my code :
private void SetUpMap()
{
if (GMap == null)
{
ChildFragmentManager.FindFragmentById<MapFragment>(Resource.Id.googlemap).GetMapAsync(this);
}
}
public void OnMapReady(GoogleMap googleMap)
{
this.GMap = googleMap;
GMap.UiSettings.ZoomControlsEnabled = true;
LatLng latlng = new LatLng(Convert.ToDouble(gpsLatitude), Convert.ToDouble(gpsLongitude));
CameraUpdate camera = CameraUpdateFactory.NewLatLngZoom(latlng, 15);
GMap.MoveCamera(camera);
MarkerOptions options = new MarkerOptions()
.SetPosition(latlng)
.SetTitle("Chennai");
GMap.AddMarker(options);
}
I got my answer from this post :
Adding polyline between two locations google maps api v2
I converted the java code to C# and it worked fine.

Rendering only polygons inside the view boundries: Google Maps Android

I have a few clickable polygons as a ArrayList. Is there a way to render polygons that are inside the view boundaries, i.e. visible only at the zoom level? Rather than rendering all of them.
you can add polygons to the map with visibile off and make them visibility on according to google map camera changes.
Polygon polygon = map.addPolygon(new PolygonOptions()
.add(new LatLng(0, 0), new LatLng(0, 5), new LatLng(3, 5), new LatLng(0, 0))
.strokeColor(Color.RED)
.fillColor(Color.BLUE)
.visibility(false);
Add camera change listener to GoogleMap instance.
googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
if (cameraPosition.zoom > 12) { // Your zoom level to show polygon
polygon.setVisible(true);
}
}
});
You can implement additional cases if you need as CameraPosition has more data apart the zoom level. Hope it helped :)
EDIT
To improve handling of many poligons, you could put all your polygons in arraylist and after the camera change, inspect which polygon should be shown:
List<Polygon> polygons = new ArrayList<>();
polygons.add(map.addPolygon(new PolygonOptions()
.add(new LatLng(0, 0), new LatLng(0, 5), new LatLng(3, 5), new LatLng(0, 0))
.strokeColor(Color.RED)
.fillColor(Color.BLUE)
.visibility(false)); //Repeat for as many as you have
In camera change listener:
if (cameraPosition.zoom > 12) { // Your required zoom level to show polygons
LatLngBounds latLngBounds = googleMap.getProjection().getVisibleRegion().latLngBounds;
for (Polygon polygon : polygons) {
for (LatLng latLng : polygon.getPoints()) {
if (latLngBounds.contains(latLng)) {
polygon.setVisible(true);
break; //Needed if only one polygon can be visible at a time, remove if several can be visible at a time
}
}
}
}
NOTE I think this should work, but I did not test this, hope it helped :)

WP8 Deleting Images from Map (Error when navigating back to page)

I have a Map that has several Images placed on it (inside the page_loaded event)
MapLayer pinLayer = new MapLayer();
MapOverlay pin50 = new MapOverlay();
pin50.GeoCoordinate = new GeoCoordinate(49.42563670946435, -0.44644108276367537);
Canvas myCanvas50 = new Canvas();
// The image is defined globally
pin50.PositionOrigin = new Point(0.5, 0.5);
image50.Source = new BitmapImage(new Uri("Images/Destroyer.png", UriKind.Relative));
image50.Opacity = 1;
Point point50 = new Point(1.0, 1.0);
Canvas.SetLeft(image50, point50.X);
Canvas.SetTop(image50, point50.Y);
myCanvas50.Children.Add(image50); // <=== ERROR OCCURS HERE
// Making an event handler for the image so that we can 'tap' on it
image50.DoubleTap += image50_DoubleTap;
pin50.Content = myCanvas50;
pinLayer50.Add(pin50);
map_J.Layers.Add(pinLayer);
It works fine for all of the Images, however when I click on an Image it navigates to a new page and gives a description of the Image that was clicked on.
The problem is that when a user navigates back to this map (by intuitively pressing the hardware BACK BUTTON) the app crashes due to the error "Element is already the child of another element."
I'm guessing that the page is still loaded so when it is navigated back to it gets 're-loaded' so can't add the same Image to the same canvas etc.
I tried adding the following to clear all information from the map before navigating away from the page but it doesn't help:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var toRemove = new List<MapLayer>();
foreach (MapLayer lyr in map_J.Layers)
{
toRemove.Add(lyr);
}
// now do the actual removal
foreach (var child in toRemove)
{
map_J.Layers.Remove(child);
}
}
Any ideas? Is there a better way to handle the reloading of the map/elements?
I would recommend clearing the map layers everytime the user leaves the page.
Add this code to the main tag in the XAML code of the view:
<phone:PhoneApplicationPage
...
Unloaded="PhoneApplicationPage_Unloaded" >
And this event code behind:
private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
{
map_J.Layers.Clear();
}

Geolocator position changed event

I am developing a running tracker/pedometer app, I am using geolocator for the same,I am keeping the movement threshold property of the geoLocator to 10 here is my piece of code.
button click event
private void StartButton_Click(object sender, RoutedEventArgs e)
{
myLocator = new Geolocator();
myLocator.DesiredAccuracy = PositionAccuracy.Default;
myLocator.MovementThreshold = 10;
myLocator.ReportInterval=500;
myLocator.PositionChanged += myGeoLocator_PositionChanged;
_startTime = System.Environment.TickCount;
_timer.Start();
}
void myGeoLocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
Dispatcher.BeginInvoke(() =>
{
var coord = new GeoCoordinate(args.Position.Coordinate.Latitude, args.Position.Coordinate.Longitude);
if (_line.Path.Count > 0)
{
var previousPoint = _line.Path.Last();
distance += coord.GetDistanceTo(previousPoint);
var millisPerKilometer = (1000.0 / distance) * (System.Environment.TickCount - _previousPositionChangeTick);
_kilometres += Math.Round(distance, 2);
distanceLabel.Text = string.Format("{0:f2} meters", _kilometres);
MessageBox.Show("Changed");
}
else
{
Map.Center = coord;
}
_line.Path.Add(coord);
_previousPositionChangeTick = System.Environment.TickCount;
});
}
The problem is that the position changed event is only getting called once, I am trying to debug the code in emulator by changing the location points but still the event do not get called. where am I doing wrong??
Your code will work on a real device. However, in order to test on the emulator, try by setting the DesiredAccuracy property to High.
From How to test apps that use location data for Windows Phone:
If your app uses the GeoCoordinateWatcher class, you have to specify a value of GeoPositionAccuracy.High in the constructor or in the DesiredAccuracy property of the class before you can test your app with the location sensor simulator. If you leave the accuracy at its default value of GeoPositionAccuracy.Default, the PositionChanged event doesn’t recognize position changes that occur in the location sensor simulator.
There is also another workaround, that consists on running the native Maps app, which seems to fix the problem:
Set a current location in the emulator.
Run your app. It reports the current location as Redmond.
Run the Maps application. It correctly goes to the location set in
step 1.
Run your app again. Now it uses the correct current location.
Source: http://social.msdn.microsoft.com/Forums/wpapps/en-US/c2cc57b1-ba1f-48fb-b285-d6cfbb8f393a/windows-phone-8-emulator-returns-microsofts-location-only