Reputation: 1235
I have a very basic Xamarin.Forms app, where I try to access an Image. This works fine when the image is in the necessary folder e.g
However when I add a folder into the mix it doesn't display anything:
Here is the line I am using:
<Image Source="btc.png" HeightRequest="20" WidthRequest="20" />
Here is the line that doesn't work:
<Image Source="Logos\btc.png" HeightRequest="20" WidthRequest="20" />
I have triple checked all backslashes and spellings/capital letters.
Upvotes: 4
Views: 4745
Reputation: 2447
Yes unfortunately you can't make use of sub-folders for android images but you can for the other 2 platforms and to account for the difference here's what I typically do.
Use the following AssetPathHelper (modify for your needs, in the below I only use a sub-folder for UWP images, and for lottie animations I use a sub-folder in both UWP and iOS). Also I assume .png, if you use other image types then need to handle that.
public static class AssetPathHelper
{
public static readonly string UWPimgRoot = @"Assets\Images\";
public static readonly string UWPanimRoot = @"Assets\Animations\";
public static readonly string iOSanimRoot = @"Animations/"; //note the different slash here, not sure if it's required but that is what works
public static string GetImageSource(string resourceName)
{
var imgFileName = resourceName + ".png"; //! obviously this requires all images used to be pngs
if (Device.RuntimePlatform != Device.UWP)
return imgFileName;
return UWPimgRoot + imgFileName;
}
public static string GetLottieAnimSource(string resourceName)
{
var animFileName = resourceName + ".json";
switch (Device.RuntimePlatform)
{
case Device.iOS:
return iOSanimRoot + animFileName;
case Device.UWP:
return UWPanimRoot + animFileName;
}
return animFileName;
}
}
which gets used in the following Converter:
/// <summary>
/// Provides the path to the image taking into account the platform specific location.
/// Can be used without a real binding (i.e. when only a parameter is provided)
/// </summary>
public class ImagePathConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter != null)
return AssetPathHelper.GetImageSource(parameter.ToString());
return AssetPathHelper.GetImageSource(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
So now in my XAML I can just do this, either as a real binding if the image will be changing or if not, then just passing the image name as the converter parameter:
<Image
Source="{Binding ConverterParameter=logo_splash, Converter={StaticResource ImagePathConverter}}"/>
Upvotes: 3
Reputation: 74094
TL;DR: Do not use sub-folders. ;-)
On Android when using subfolders within the Drawable
folder (and the pixel density folders, i.e: drawable-xxhpdi
), the sub-folder name is ignored but the drawable's ID are generated in the Java R.
file (C# Resources.
in Xamarin.Android
), assuming there is no invalid names or clashing. So in native Android & Xamarin.Android those drawable will have an resource ID (integer-based) assigned to them and are usable.
But, Xamarin.Forms
will not be able to find those images as a reverse lookup is used, from Name to Android resource ID and thus will be no match.
Also on iOS, the use of the Resource
folder for images via BundleResource
is deprecated and you should be using "Asset Catalog Image Sets" instead.
For more info: Images in Xamarin.Forms
Upvotes: 4