1
votes

I'm developing an app for multiple platforms using Xamarin. Shared code is hosted in a separate PCL project. The project contains a large collection of images, which I would also like to share via the PCL project.

Is that possible? How can I access the image data from my platform-specific projects?

3
You most certainly can. Even though you are using the native side, you can still use the xamarin forms library (have a look at developer.xamarin.com/guides/cross-platform/xamarin-forms/…)Johan

3 Answers

2
votes

You should put your images in each separate project, as each platform has different images resolutions conventions, and in order to optimize and display properly the images, you'll need to save the images in different projects with the OS specific convention.

You can refer the image file in the PCL project like this:

beachImage.Source = "waterfront.png"; where waterfront is defined in each OS project by the following conventions:

Android images should be placed in Resources\Drawable\{specificResolution}

Android has these resolutions (taken from Android developer site):

ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi

Note that each resolution has it's own folder for images.

In iOS you have these resolutions (taken from iOS Human Interface Guidelines ): iOS Resolutions

You should separate your images by adding a '@2x' or '@3x' in your Resources folder.

1
votes

What I finally did (until now, I could only verify on an iOS and Droid project, Windows Phone is still in the works):

I return the image data from my shared project as Stream, as in:

public Stream GetImageStream () {
    return assembly.GetManifestResourceStream (nameOfResource);
}

Images' properties are set to EmbeddedResource. In my iOS project, I can then access my image like so:

using (var stream = myClass.GetImageStream ()) {
    var image = new UIImage (NSData.FromStream (stream));
    // do stuff with image
}

And on Android I use the following code:

using (var stream = myClass.GetImageStream ()) {
    var bitmap = BitmapFactory.DecodeStream (stream);
    // do stuff with bitmap
}

Feedback whether there any gotchas with this practice are welcome! (beside the obvious sizing-issue, which I can live with for now, I could imagine that this approach circumvents any platform-specific caching mechanisms?)

0
votes

The ResourceManager class supported by PCL supports only a limited set of data types and Images are not one of them.

According to the MSDN article here the best way to deal with image data types is to encode the images as Base64 encoded string resources and then decode the data as a ByteArray and then load that byte array into the Image.

You will have to pre-process the images to generate the Base64 strings since that can't be done at runtime.