VISUAL STUDIO   Windows Mac

Images

Loading and displaying images in Xamarin.Forms

PDF for offline use
Sample Code:
Related Articles:

Let us know how you feel about this

Translation Quality


0/250

last updated: 2017-08

Images can be shared across platforms with Xamarin.Forms, they can be loaded specifically for each platform, or they can be downloaded for display.

Overview

Images are a crucial part of application navigation, usability, and branding. Xamarin.Forms applications need to be able to share images across all platforms, but also potentially display different images on each platform.

Platform-specific images are also required for icons and splash screens; these need to be configured on a per-platform basis.

This document discusses the following topics:

  • Local images - displaying images shipped with the application, including resolving native resolutions like iOS Retina or Android high-DPI versions of an image.
  • Embedded images - displaying images embedded as an assembly resource.
  • Downloaded images - downloading and displaying images.
  • Icons and splashscreens - platform-specific icons and start-up images.

Displaying Images

Xamarin.Forms uses the Image view to display images on a page. It has two important properties:

  • Source - An ImageSource instance, either File, Uri or Resource, which sets the image to display.
  • Aspect - How to size the image within the bounds it is being displayed within (whether to stretch, crop or letterbox).

ImageSource instances can be obtained using static methods for each type of image source:

  • FromFile - Requires a filename or filepath that can be resolved on each platform.
  • FromUri - Requires a Uri object, eg. new Uri("http://server.com/image.jpg") .
  • FromResource - Requires a resource identifier to an image file embedded in the application or PCL, with a Build Action:EmbeddedResource.
  • FromStream - Requires a stream that supplies image data.

The Aspect property determines how the image will be scaled to fit the display area:

  • Fill - Stretches the image to completely and exactly fill the display area. This may result in the image being distorted.
  • AspectFill - Clips the image so that it fills the display area while preserving the aspect (ie. no distortion).
  • AspectFit - Letterboxes the image (if required) so that the entire image fits into the display area, with blank space added to the top/bottom or sides depending on the whether the image is wide or tall.

Images can be loaded from a local file, an embedded resource, or downloaded.

Local Images

Image files can be added to each application project and referenced from Xamarin.Forms shared code. To use a single image across all apps, the same filename must be used on every platform, and it should be a valid Android resource name (ie. only lowercase letters, numerals, the underscore, and the period are allowed).

  • iOS - The preferred way to manage and support images since iOS 9 is to use Asset Catalog Image Sets, which should contain all of the versions of an image that are necessary to support various devices and scale factors for an application. For more information, see Adding Images to an Asset Catalog Image Set.
  • Android - Place images in the Resources/drawable directory with Build Action: AndroidResource. High- and low-DPI versions of an image can also be supplied (in appropriately named Resources subdirectories such as drawable-ldpi, drawable-hdpi, and drawable-xhdpi).
  • Windows Phone - Place images in the application's root directory with Build Action: Content.
  • Universal Windows Platform (UWP) - Place images in the application's root directory with Build Action: Content.
⚠️

Prior to iOS 9, images were typically placed in the Resources folder with Build Action: BundleResource. However, this method of working with images in an iOS app has been deprecated by Apple. For more information, see Image Sizes and Filenames.

Adhering to these rules for file naming and placement allows the following XAML to load and display the image on all platforms:

<Image Source="waterfront.jpg" />

The equivalent C# code is as follows:

var image = new Image { Source = "waterfront.jpg" };

The following screenshots show the result of displaying a local image on each platform:

Local ImageSource

For more flexibility the Device.RuntimePlatform property can be used to select a different image file or path for some or all platforms, as shown in this code example:

image.Source = Device.RuntimePlatform == Device.Android ? ImageSource.FromFile("waterfront.jpg") : ImageSource.FromFile("Images/waterfront.jpg");
⚠️

To use the same image filename across all platforms the name must be valid on all platforms. Android drawables have naming restrictions – only lowercase letters, numbers, underscore, and period are allowed – and for cross-platform compatibility this must be followed on all the other platforms too. The example filename waterfront.png follows the rules, but examples of invalid filenames include "water front.png", "WaterFront.png", "water-front.png", and "wåterfront.png".

Native Resolutions (Retina and High-DPI)

Both iOS and Android platforms include support for different image resolutions, where the operating system chooses the appropriate image at runtime based on the device's capabilities. Xamarin.Forms uses the native platforms' APIs for loading local images, so it automatically supports alternate resolutions if the files are correctly named and located in the project.

The preferred way to manage images since iOS 9 is to drag images for each resolution required to the appropriate asset catalog image set. For more information, see Adding Images to an Asset Catalog Image Set.

Prior to iOS 9, retina versions of the image could be placed in the Resources folder - two and three times the resolution with a @2x or @3x suffixes on the filename before the file extension (eg. myimage@2x.png). However, this method of working with images in an iOS app has been deprecated by Apple. For more information, see Image Sizes and Filenames.

Android alternate resolution images should be placed in specially-named directories in the Android project, as shown in the following screenshot:

Android Multiple-Resolution Image Location

Additional Controls that Display Images

Some controls have properties that display an image, such as:

  • Page - Any page type that derives from Page has Icon and BackgroundImage properties, which can be assigned a local file reference. Under certain circumstances, such as when a NavigationPage is displaying a ContentPage, the icon will be displayed if supported by the platform.

    ⚠️

    On iOS, the Page.Icon property can't be populated from an image in an asset catalog image set. Instead, load icon images for the Page.Icon property from the Resources folder in the iOS project.

  • ToolbarItem - Has an Icon property that can be set to a local file reference.

  • ImageCell - Has an ImageSource property that can be set to an image retrieved from a local file, an embedded resource, or a URI.

Embedded Images

Embedded images are also shipped with an application (like local images) but instead of having a copy of the image in each application's file structure the image file is embedded in the assembly as a resource. This method of distributing images is particularly suited to creating components, as the image is bundled with the code.

To embed an image in a project, right-click to add new items and select the image/s you wish to add. By default the image will have Build Action: None; this needs to be set to Build Action: EmbeddedResource.

The Build Action can also be viewed and changed in the Properties pad for a file. This pad shows the Resource ID that is used to reference the resource in code. In the screenshot below, the Resource ID is WorkingWithImages.beach.jpg. The IDE has generated this default by concatenating the Default Namespace for this project with the filename, using a period (.) between each value. This ID can be edited in the Properties pad, but for these examples the value WorkingWithImages.beach.jpg will be used.

The Build Action can be viewed and changed in the Properties window for a file.

In this example the resource ID is WorkingWithImages.beach.jpg. The IDE has generated this default by concatenating the Default Namespace for this project with the filename, using a period (.) between each value.

If you place embedded images into folders within your project, the folder names are also separated by periods (.) in the resource ID. Moving the beach.jpg image into a folder called MyImages would result in a resource ID of WorkingWithImages.MyImages.beach.jpg

The code to load an embedded image simply passes the Resource ID to the ImageSource.FromResource method as shown below:

var embeddedImage = new Image { Source = ImageSource.FromResource("WorkingWithImages.beach.jpg") };

Currently there is no implicit conversion for resource identifiers. Instead, you must use ImageSource.FromResource or new ResourceImageSource() to load embedded images.

The following screenshots show the result of displaying an embedded image on each platform:

ResourceImageSource

Using XAML

Because there is no built-in type converter from string to ResourceImageSource, these types of images cannot be natively loaded by XAML. Instead, a simple custom XAML markup extension can be written to load images using a Resource ID specified in XAML:

[ContentProperty ("Source")]
public class ImageResourceExtension : IMarkupExtension
{
 public string Source { get; set; }

 public object ProvideValue (IServiceProvider serviceProvider)
 {
   if (Source == null)
   {
     return null;
   }
   // Do your translation lookup here, using whatever method you require
   var imageSource = ImageSource.FromResource(Source);

   return imageSource;
 }
}

To use this extension add a custom xmlns to the XAML, using the correct namespace and assembly values for the project. The image source can then be set using this syntax: {local:ImageResource WorkingWithImages.beach.jpg}. A complete XAML example is shown below:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
   xmlns="http://xamarin.com/schemas/2014/forms"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
   xmlns:local="clr-namespace:WorkingWithImages;assembly=WorkingWithImages"
   x:Class="WorkingWithImages.EmbeddedImagesXaml">
 <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
   <!-- use a custom Markup Extension -->
   <Image Source="{local:ImageResource WorkingWithImages.beach.jpg}" />
 </StackLayout>
</ContentPage>

Troubleshooting Embedded Images

Debugging Code

Because it is sometimes difficult to understand why a particular image resource isn't being loaded, the following debug code can be added temporarily to an application to help confirm the resources are correctly configured. It will output all known resources embedded in the given assembly to the Console to help debug resource loading issues.

using System.Reflection;
// ...
// NOTE: use for debugging, not in released app code!
var assembly = typeof(EmbeddedImages).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
{
    System.Diagnostics.Debug.WriteLine("found resource: " + res);
}

Images Embedded in Other Projects Don't Appear

Image.FromResource only looks for images in the same assembly as the code calling FromResource. Using the debug code above you can determine which assemblies contain a specific resource by changing the typeof() statement to a Type known to be in each assembly.

Downloading Images

Images can be automatically downloaded for display, as shown in the following XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       x:Class="WorkingWithImages.DownloadImagesXaml">
  <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
    <Label Text="Image UriSource Xaml" />
    <Image Source="https://xamarin.com/content/images/pages/forms/example-app.png" />
    <Label Text="example-app.png gets downloaded from xamarin.com" />
  </StackLayout>
</ContentPage>

The equivalent C# code is as follows:

var webImage = new Image { Source = ImageSource.FromUri(new Uri("https://xamarin.com/content/images/pages/forms/example-app.png")) };

The ImageSource.FromUri method requires a Uri object, and returns a new UriImageSource that reads from the Uri.

There is also an implicit conversion for URI strings, so the following example will also work:

webImage.Source = "https://xamarin.com/content/images/pages/forms/example-app.png";

The following screenshots show the result of displaying a remote image on each platform:

Downloaded ImageSource

Downloaded Image Caching

A UriImageSource also supports caching of downloaded images, configured through the following properties:

  • CachingEnabled - Whether caching is enabled (true by default).
  • CacheValidity - A TimeSpan that defines how long the image will be stored locally.

Caching is enabled by default and will store the image locally for 24 hours. To disable caching for a particular image, instantiate the image source as follows:

image.Source = new UriImageSource { CachingEnabled = false, Uri="http://server.com/image" };

To set a specific cache period (for example, 5 days) instantiate the image source as follows:

webImage.Source = new UriImageSource
{
    Uri = new Uri("https://xamarin.com/content/images/pages/forms/example-app.png"),
    CachingEnabled = true,
    CacheValidity = new TimeSpan(5,0,0,0)
};

Built-in caching makes it very easy to support scenarios like scrolling lists of images, where you can set (or bind) an image in each cell and let the built-in cache take care of re-loading the image when the cell is scrolled back into view.

Icons and splashscreens

While not related to the Image view, application icons and splashscreens are also an important use of images in Xamarin.Forms projects.

Setting icons and splashscreens for Xamarin.Forms apps is done in each of the application projects. This means generating correctly sized images for iOS, Android, and UWP. These images should be named and located according to each platforms' requirements.

Icons

See the iOS Working with Images, Google Iconography, and Guidelines for tile and icon assets for more information on creating these application resources.

Splashscreens

Only iOS and UWP applications require a splashscreen (also called a startup screen or default image).

Refer to the documentation for iOS Working with Images and Splash screens on the Windows Dev Center.

Summary

Xamarin.Forms offers a number of different ways to include images in a cross-platform application, allowing for the same image to be used across platforms or for platform-specific images to be specified. Downloaded images are also automatically cached, automating a common coding scenario.

Application icon and splashscreen images are set-up and configured as for non-Xamarin.Forms applications - follow the same guidance used for platform-specific apps.

Xamarin Workbook

If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.