question

FerryCathal-2954 avatar image
0 Votes"
FerryCathal-2954 asked RobCaplan edited

Xamarin Maps dynamically chance icon based on proximity

Hello,
I am quite new to Xamarin and am developing a simple app that uses xamrin maps.
I have my own location and a service that checks if my position on the map changes (using guides and documentation i followed).
One of things ive implemented was custom pins using a custom renderer, ive followed a guide for this quite successfully.
I am using xamarin essentials CalculateDistance function to get the distance between me and a pin and currently showing a message to which pin i am closest to, by means of swapping in a larger pin whne close to it.

What i am struggling with is how to change the pin size dynamically when the map has loaded.
my app on launch will get my proximity to a pin and show it as large if i am nearby just fine but i cannot get the map to refresh the pins and show the pin changing in size depending on if am in close proximity or not.

I have tried to use my location changing function to trigger my code to check my proximity and redraw the pins but it doesnt work on the map.

I read my pin data from a JSON and get my location from GPS and compare it to the pins location using the following code in my mainpage.

I have tried pin.clear and pin.remove instead of my pin.add function but this doesnt work.
I have commented out the Content=customMap in my proximity checking code as this will just refresh the map over and over.
Below is the code i use to try and update my pins dynamically, this does fire when my GPS location changes. the getDist function returns a string to state if i am close to a pin or not. it just uses the CalculateDistance function from Xamarin.Essentials.

Can anybody help me out as i am struggling with it. Apologies if i havent included other code/services etc. let me know if you need it.

I have two main methods one of which doesnt trigger the custom map rendered, UpdateMaps fires on launch and draws the pins in my JSON file.
UpdateMaps3 is a copy of this with some minor changes. UpdateMaps3 is fired when the users position changes but the part where it should override the createMarker method in my custom map renderer never fires.
Is it that i am missing something obvious? I just am not sure what is going on.
Thanks

 using System;
 using System.IO;
 using System.Reflection;
 using Xamarin.Forms;
 using Newtonsoft.Json;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Threading.Tasks;
 using Xamarin.Forms.Maps;
 using Xamarin.Essentials;
 using Distance = Xamarin.Forms.Maps.Distance;
 using Google.Protobuf.WellKnownTypes;
 using static Google.Protobuf.Reflection.FieldDescriptorProto.Types;
    
 namespace MAPS.Views
 {
     public partial class AboutPage : ContentPage
     {
         IlocationUpdateService loc;
         
         public AboutPage()
         {
             InitializeComponent();
             Task.Delay(2000);
             UpdateMap();
         }
         async void OnActionSheetCancelDeleteClicked()
         {
             bool answer = await DisplayAlert("Location Request", "Please enable location services to use this app", "Settings", "Cancel");
             if (answer == true)
             {
                 DependencyService.Get<ILocSettings>().OpenSettings();
             }
         }
         protected override void OnAppearing()
         {
             base.OnAppearing();
             bool gpsStat = DependencyService.Get<ILocSettings>().isGpsAvailable();
             if (gpsStat == false)
             {
                 OnActionSheetCancelDeleteClicked();
             }
    
             loc = DependencyService.Get<IlocationUpdateService>();
    
             loc.LocationChanged += (object sender, ILocationEventArgs args) =>
               {
    
                   String lat1 = args.Latitude.ToString();
                   String lng1 = args.Longitude.ToString();
                   UpdateMap3(lat1, lng1);
               };
             loc.GetUsedLocation();
      
         }
            
         protected override void OnDisappearing()
         {
             base.OnDisappearing();
             loc = null;
    
         }
         List<Place> placesList = new List<Place>();
         private async void UpdateMap()
         {
             var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
                 Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
                 string text = string.Empty;
                 using (var reader = new StreamReader(stream))
                 {
                     text = reader.ReadToEnd();
                 }
                 var resultObject = JsonConvert.DeserializeObject<Places>(text);
                 var request = new Xamarin.Essentials.GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(30));
                 var location = await Geolocation.GetLocationAsync(request);
             CustomMap customMap = new CustomMap()
             {
                 IsShowingUser = true
    
             };
             customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
    
             foreach (var place in resultObject.results)
             {
                 Location location1 = new Location(place.geometry.location.lat,place.geometry.location.lng);
                 string color = getDist(location1, location);
                 if (color == "purple")
                 {
                     CustomPin pin = new CustomPin()
                     {
    
                         Type = PinType.Place,
                         Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
                         Label = place.id,
                         Address = place.vicinity+"*",
                         Name = "Xamarin",
                         icon = "icon.png",
                         Url = "http://xamarin.com/about/"
                     };
    
                     customMap.Pins.Add(pin);
                        
                 }
                 else
                 {
                     CustomPin pin = new CustomPin()
                     {
    
                         Type = PinType.Place,
                         Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
                         Label = place.id,
                         Address = place.vicinity,
                         Name = "Xamarin",
                         icon = "pin.png",
                         Url = "http://xamarin.com/about/"
                     };
    
                     customMap.Pins.Add(pin);
                 }
             }
                 customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(location.Latitude, location.Longitude), Distance.FromKilometers(0.15))); ;
             Content = customMap;
       }
         public  string getDist(Location loc, Xamarin.Essentials.Location currentLoc)
         {
             string color = "red";
             //  bool geo = false;
             double latEnd = loc.lat;
             double lngEnd = loc.lng;
             ///  Position(currentLoc.lat, currentLoc.lng);
             double dist = currentLoc.CalculateDistance(latEnd, lngEnd, DistanceUnits.Kilometers);
             if (dist < 0.05) //5m distance
             {
    
                 color = "purple";
    
    
    
             }
             else
             {
                 color = "red";
             }
             return color;
         }
     public void getNewPins()
         {
             InitializeComponent();
    
         }
  public void getPin()
         {
             var pr = new PopUp();
         }
    
    
         private void UpdateMap3(String lat, String lng)
         {
             var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
             Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
             string text = string.Empty;
             using (var reader = new StreamReader(stream))
             {
                 text = reader.ReadToEnd();
             }
             var resultObject = JsonConvert.DeserializeObject<Places>(text);
             //  var request = new Xamarin.Essentials.GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(30));
             //  var location = await Geolocation.GetLocationAsync(request);
             CustomMap customMap = new CustomMap()
             {
                 IsShowingUser = true
    
             };
    
             customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
    
             foreach (var place in resultObject.results)
             {
                 Location location1 = new Location(place.geometry.location.lat, place.geometry.location.lng);
                 Xamarin.Essentials.Location location = new Xamarin.Essentials.Location(Convert.ToDouble(lat), Convert.ToDouble(lng));
                 string color = getDist(location1, location);
    
                 if (color == "purple")
                 {
                     CustomPin pin2 = new CustomPin()
                     {
    
                         Type = PinType.Place,
                         Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
                         Label = place.id,
                         Address = place.vicinity,
                         Name = "Xamarin",
                         icon = "icon.png",
                         Url = "http://xamarin.com/about/"
                     };
                       
                     customMap.Pins.Add(pin2);
                     // customMap.Pins.Clear();
                     //  customMap.CustomPins.Clear();
                     //   customMap.Pins.Remove(pin);
                     //    customMap.CustomPins.Remove(pin);
                     //  await  customMap.Pins.Remove(pin);
                     //  await DisplayAlert("Alert", "You are near  it is KM from you.", "OK");
                 }
                 else
                 {
                     CustomPin pin2 = new CustomPin()
                     {
    
                         Type = PinType.Place,
                         Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
                         Label = place.id,
                         Address = place.vicinity+"*",
                         Name = "Xamarin",
                         icon = "pin.png",
                         Url = "http://xamarin.com/about/"
                     };
    
                     customMap.Pins.Add(pin2);
                     // customMap.CustomPins.Remove(pin);
                 }
             }
             //   customMap.Pins.Clear();
    
    
             //   customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(Convert.ToDouble(lat), Convert.ToDouble(lng)), Distance.FromKilometers(0.15))); ;
           //  Content = customMap;
    
            // customMap.Pins.Add(pins);
         }
     }
     }


dotnet-xamarin
· 9
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, FerryCathal. To change the icon of the pin on Android, try to override the CreateMarker method in the custom renderer class.

Check the doc:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/map-pin#customizing-the-marker

0 Votes 0 ·

Hello JarvanZhang-MSFT,
i have my CreateMarker method overridden in my Android Custom renderer class from following the documentation linked but and a tutorial but it never seems to fire outside of loading up the page for the first time.

Thanks

0 Votes 0 ·

but it never seems to fire outside of loading up the page for the first time.

Please make sure you've used the custom Map control in the page and check the registration of the custom renderer class. You could refer to the official sample code.
https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/customrenderers-map-pin/

0 Votes 0 ·
Show more comments

0 Answers