amay077 / Xamarin.Forms.GoogleMaps

Map library for Xamarin.Forms using Google maps API
https://www.nuget.org/packages/Xamarin.Forms.GoogleMaps/
MIT License
546 stars 346 forks source link

Load Pin Image from Resources in Android #617

Open ravero opened 5 years ago

ravero commented 5 years ago

SUMMARY

BitmapDescriptorFactory should provide a way from loading Pin Icon from a Resource Drawable. This is important because rendering directly from the Assets folder doesn't take into account the image densities, and would render incorrect size or low quality pin images.

DETAILS

Google Maps Android SDK actually provides a method from loading for loading Marker bitmap from resource.

My suggestion is to add a FromResource method to the BitmapDescriptorFactory class. When rendering on Android, it should call the previously mentioned method to load icon from the Resources. When loaded from other platforms, it should mimics the behaviour of FromBundle, since there's no equivalent of resources in iOS or UWP.

The usage would be as follows:

pin.Icon = BitmapDescriptorFactory.FromResource("resource_name");

PLATFORMS

amay077 commented 5 years ago

Hi @ravero , you're correct.

Currently supported icon types are below table.

X.F.GoogleMaps Android iOS
Default defaultMarker markerImage
Bundle fromAsset fromBundle
Stream fromBitmap UIImage.LoadFromData
AbsolutePath fromPath UiImage.FromFile
N/A FromResource N/A

I can't support Android's FromResource because I have 2 reasons.

  1. FromResource is only for Android, iOS and UWP can't support it
  2. Android's resource Id is number type and auto generate constants(like Resource.Drawable.your_awesome_drawable_1), but these constants can't use in Xamarin.Forms project.

My suggested solution is make your own BitmapDescriptorFactory implemented from IBitmapDescriptorFactory.

ref - https://github.com/amay077/Xamarin.Forms.GoogleMaps/issues/436#issuecomment-430616158

ravero commented 5 years ago

I took the solution of overriding the default BitmapDescriptorFactory, it works but I still think that it's possible to add a built-in solution.

In my project I don't reference the Drawable by it's internal int Id, but by it's name, and I map the Bundle name of the descriptor as the base resource:

context.Resources.GetIdentifier(descriptor.BundleName, "drawable", context.ApplicationInfo.PackageName);

This command resolves the name to the int resource identifier. As I said before, FromResource could be mapped to UIImage.FromFile on iOS, this way we could provide a unified solution.

The required context object to translate name into resource Id could be get from the initialization code requests the context.

To me seems a pretty elegant solution. Maybe we could put that on vote.