Custom google map marker icon load only after move map

Liuk88Liuk88 ITMember ✭✭✭

Hello guys, I'm having a strange behaviour, trying to describe it well here:

I had a project with a simple custom renderer to have a custom icon for markers in the map (and it was working)
After, I moved this project on git removing some folders (mainly debug, obj, bin) but nothing regarding the custom renderer files.
After this operation now I'm using in debug the project on git but I have this problem:
When I open the map, the markers are presented with the "standard marker icon" until I move the map (this action loads instantly the custom marker icon).
What can be this behaviour?

Thanks a lot!

Answers

  • seanydaseanyda GBMember ✭✭✭✭✭
    edited December 2017

    Show some code for the custom renderer? I don't think a custom renderer is necessary though, I set custom icons via the package itself.

    Set the icon of the Pin
    Icon = SetPinIconStream("EMBEDDEDRESOURCE");

    EmbeddedResource will mean, If you have a image called "Test.png" in your Images folder in your PCL, You would use SOLUTIONNAME.Images.test.png

    You'll need this helper method too

        BitmapDescriptor SetPinIconStream(string embeddedResource) {
                    var assembly = typeof(PageName).GetTypeInfo().Assembly;
                    var stream = assembly.GetManifestResourceStream($"" + embeddedResource);
                    return BitmapDescriptorFactory.FromStream(stream);
                }
    

    Modify "PageName" with the name of the Page e.g Dashboard, Login

    This solution will save you making a custom renderer for each platform your using the map control :)

  • Liuk88Liuk88 ITMember ✭✭✭
    edited December 2017

    Hi Seanyda, thanks for reply :)
    Few minutes ago I discovered that the error is caused from an upgrade of Xamarin Forms recently done (from 2.4.x to 2.5.x)
    After the update i got the message "MapRenderer: This constructor is obsolete as of version 2.5. Please use MapRenderer(Context) instead."
    After that i modified the constructor but the problem still persists..
    If possible I would like to solve this keep using custom renderer (before the upgrade the icon behaviour was fine).
    Here i copy the code I'm using (is not too much)

    In the main project I have this xaml file (a content page):

    <StackLayout>
            <local:CustomParkingMap x:Name="ParkingMap"
                      IsShowingUser="true"
                      VerticalOptions="FillAndExpand"
                      HorizontalOptions="FillAndExpand"
            />
        </StackLayout>
    

    with the relative xaml.cs that basically does:

            //here i have a list of markers retrieved from a source
            List<ParkingSpots> parkingSpots = ....
    
                    foreach (var p in parkingSpots)
                    {
                        var pin = new Pin
                        {
                            Type = PinType.Place,
                            Position = new Position(p.Lat, p.Lon),
                            Label = p.Name,
                            Address = "someAdress"
                        };
                        ParkingMap.Pins.Add(pin);
                    }
    

    Finally in the Android project I have the custom renderer with basically 2 methods:

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs

    e)
    {
    base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                var map = (CustomParkingMap)e.NewElement;
                customPins = map.Pins;
                Control.GetMapAsync(this);
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
    
            if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
            {
                NativeMap.Clear();
    
                foreach (var pin in customPins)
                {
                    var marker = new MarkerOptions();
                    marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
                    marker.SetTitle(pin.Label);
                    marker.SetSnippet(pin.Address);
            //HERE I SET THE NEW ICON
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.parking));
    
                    NativeMap.AddMarker(marker);
                }
                isDrawn = true;
            }
        }
    

    I remember that this code was all working before the update while after i need to move the map to load the new icon...(I built it following the custom renderers docs/some posts, could be not the best solution..)

  • seanydaseanyda GBMember ✭✭✭✭✭

    @Liuk88 said:
    Hi Seanyda, thanks for reply :)
    Few minutes ago I discovered that the error is caused from an upgrade of Xamarin Forms recently done (from 2.4.x to 2.5.x)
    After the update i got the message "MapRenderer: This constructor is obsolete as of version 2.5. Please use MapRenderer(Context) instead."
    After that i modified the constructor but the problem still persists..
    If possible I would like to solve this keep using custom renderer (before the upgrade the icon behaviour was fine).
    Here i copy the code I'm using (is not too much)

    In the main project I have this xaml file (a content page):



    with the relative xaml.cs that basically does:

          //here i have a list of markers retrieved from a source
          List<ParkingSpots> parkingSpots = ....
    
                  foreach (var p in parkingSpots)
                  {
                      var pin = new Pin
                      {
                          Type = PinType.Place,
                          Position = new Position(p.Lat, p.Lon),
                          Label = p.Name,
                          Address = "someAdress"
                      };
                      ParkingMap.Pins.Add(pin);
                  }
    

    Finally in the Android project I have the custom renderer with basically 2 methods:

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs

    e)
    {
    base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                var map = (CustomParkingMap)e.NewElement;
                customPins = map.Pins;
                Control.GetMapAsync(this);
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
    
            if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
            {
                NativeMap.Clear();
    
                foreach (var pin in customPins)
                {
                    var marker = new MarkerOptions();
                    marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
                    marker.SetTitle(pin.Label);
                    marker.SetSnippet(pin.Address);
          //HERE I SET THE NEW ICON
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.parking));
    
                    NativeMap.AddMarker(marker);
                }
                isDrawn = true;
            }
        }
    

    I remember that this code was all working before the update while after i need to move the map to load the new icon...(I built it following the custom renderers docs/some posts, could be not the best solution..)

    From a quick glance at the code, That all looks ok. Without doing some debugging and running the build I probably can't assist. For me though, It would be such a quicker solution to copy the helper method in and move this logic into the PCL, Because If you're ever going to have this app on any platform other then Android you're going to be duplicating a lot of code.

  • Liuk88Liuk88 ITMember ✭✭✭

    Yes your solution is easier, btw seems I solved the problem with custom renderer too...I noticed this method in the Xamarin doc here:
    https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/customized-pin/#Customizing_the_Marker

    protected override MarkerOptions CreateMarker(Pin pin)
    {
    var marker = new MarkerOptions();
    marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
    marker.SetTitle(pin.Label);
    marker.SetSnippet(pin.Address);
    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
    return marker;
    }

    Adding the above method in my custom renderer and removing the OnElementPropertyChanged (now useless I think) solved the issue.
    Plus in the doc page I linked the OnElementPropertyChanged method is not mentioned anymore..so I guess now this is the right approach for customize markers..what do you think?

    Thanks again for your help :)

  • seanydaseanyda GBMember ✭✭✭✭✭

    @Liuk88 said:
    Yes your solution is easier, btw seems I solved the problem with custom renderer too...I noticed this method in the Xamarin doc here:
    https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/customized-pin/#Customizing_the_Marker

    protected override MarkerOptions CreateMarker(Pin pin)
    {
    var marker = new MarkerOptions();
    marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
    marker.SetTitle(pin.Label);
    marker.SetSnippet(pin.Address);
    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
    return marker;
    }

    Adding the above method in my custom renderer and removing the OnElementPropertyChanged (now useless I think) solved the issue.
    Plus in the doc page I linked the OnElementPropertyChanged method is not mentioned anymore..so I guess now this is the right approach for customize markers..what do you think?

    Thanks again for your help :)

    Nice job glad to hear you sorted it. Yeah that most likely is the correct approach for a Xamarin.Android application, but if you were to be building it for iOS and Windows too it might make sense to go down the cross-platform approach, You can always refer back if need be!

  • Liuk88Liuk88 ITMember ✭✭✭

    You right, because for example for IOS the custom renderer in the doc have bigger code than the Android one (just to have a marker customization) and an approach like your could be faster and simpler. I just using custom render in order to learn a bit of them :)

Sign In or Register to comment.