Cross Platform
Android
iOS
Mac
Test Cloud

Working with Images

Loading and displaying images in Xamarin.Forms

Show instructions for:

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, useability, 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:

  • 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.

Image and ImageSource

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 are easy to obtain 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 .

The Aspect 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 (which means no spaces and special characters).

  • iOS - Place images in the Resources folder with Build Action: BundleResource . Retina versions of the image should also be supplied - twice the resolution with an "@2x" suffix on the filename before the file extension.
  • 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 .

This screenshot shows the Xamarin.Forms solution, with an image file present in each application project:

Adhering to those rules for file naming and placement allows two lines of shared code to load and display the image on all platforms:

var beachImage = new Image { Aspect = Aspect.AspectFit };
beachImage.Source = ImageSource.FromFile("waterfront.jpg");

Even better, there is an implicit conversion so that this line also works:

beachImage.Source = "waterfront.jpg";

The image file itself can be duplicated (ie. copied into each application project) or saved in a single location and file-linked into the correct directories.

Local ImageSource

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

beachImage.Source =  Device.OnPlatform(
            iOS: ImageSource.FromFile("Images/waterfront.jpg")),
            Android:  ImageSource.FromFile("waterfront.jpg"),
            WinPhone: ImageSource.FromFile("Images/waterfront.png"));

Using Xaml

The same image can be referenced in a Xaml page as shown here:

<?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.LocalImagesXaml">
  <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
    <Label Text="ImageSource.FromFile" />
    <Image Source="waterfront.jpg" />
    <Label Text="'waterfront.jpg' is referenced in Xaml" />
  </StackLayout>
</ContentPage>

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. The Xamarin.Forms ImageSource 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.

iOS Retina images should be placed in the same location as the non-Retina image, with an "@2x" suffix on the filename. This screenshot shows the normal and Retina images in the iOS project of the Xamarin.Forms WorkingWithImages sample:

Retina Image Location

Android alternate resolution images should be placed in specially-named directories in the Android project:

Android Multiple-Resolution Image Location

Only the FileImageSource will automatically load alternate-resolution images; the ResourceImageSource and UriImageSource described below do not.

Controls that use Images

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

  • Page - Anything that inherits from Page has string Icon and BackgroundImage properties, which can be assigned a local file reference. When these pages are used in a navigation control as tabs or master-detail the icon will be displayed if the platform supports it. Treat this like a FileImageSource and place the icon image file in each of the application projects.
  • ToolbarItem - Has an Icon property similar to the Page.Icon property, a string that can be set to a local file reference.
  • ImageCell - Used with ListView and TableView controls, has an Image property whose source can be set. The ImageSource can be any of the supported types (File, Uri or Resource).

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.

Set 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 Assembly Name 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.

EmbeddedResource Properties Pad
Set Build Action: EmbeddedResource

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 Assembly Name 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 here:

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

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

ResourceImageSource

Debugging Embedded Images

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);

Using Xaml

Because there is no built-in type converter from string to ResourceImageSource, these types of images cannot be natively loaded by Xaml.

To get around this restriction, 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 here:

<?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>

Downloading Images

The UriImageSource can automatically download an image for display. It requries a Uri object, which can be initialized with a valid image URL.

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

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

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

Downloaded ImageSource

Using Xaml

The same image can be downloaded in a Xaml page as shown in here:

<?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="http://xamarin.com/content/images/pages/forms/example-app.png" />
    <Label Text="example-app.png gets downloaded from xamarin.com" />
  </StackLayout>
</ContentPage>

Downloaded Image Caching

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 like this:

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 like this:

webImage.Source = new UriImageSource {
    Uri = new Uri("http://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 class, 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 each of iOS, Android, and Windows Phone. These images should be named and located according to each platforms' requirements.

Icons

See the iOS Working with Images, Google Iconography, and Tile Design Guidelines for Windows Phone for more information on creating these application resources

Splashscreens

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

Refer to the documentation for iOS Working with Images and Splash screens in Multi-resolution apps for Windows Phone 8.

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.