Introduction To Image Assets In Xamarin.Forms
Author: Ben Reierson
Most mobile apps rely heavily on the use of images, which means it's one of the first topics mobile developers need to learn. While Xamarin Forms generally makes things pretty simple, there remain a few nuances that can be somewhat confusing at first.
This article will cover the basics for managing image assets in your Xamarin Forms app. We will also cover some best practices for using images with MVVM, and look at how MFractor can help make this dramatically easier. This article is not meant as a replacement for Microsoft's own documentation, which I highly suggest you read for a more thorough understanding.
Where do I put the image files? This is a question I hear a lot from developers new to Xamarin.Forms, because it's not immediately obvious. While Xamarin Forms provides an abstraction layer that allows the vast majority of your code to reside in a single project, each platform handles images differently, so most apps reference separate copies of their images (at various resolutions) in the platform-specific projects.
Because mobile devices come in a wide variety of sizes and resolutions, we need to provide images that will scale appropriately. In order to prevent images from looking blurry on high-resolution devices, we need to start with high resolution. BUT, in order to be efficient and avoid poor performance on smaller/older devices, we also need to provide lower-resolution versions. Each platform handles this slightly differently. The good news is that using a tool like MFractor makes creating these various images easy, but we'll get to that.
Android Images 101 Android images are stored under the android project's /Resources folder in a set of folders all starting with 'drawable'.
The various drawable folders each represent a different category of display density, starting with ldpi (low dots per inch) to xxxhdpi (ludicrously high dpi). Here is a list of some of the most common devices and how they map to these categories. In general, you can think of mdpi being for old devices (almost nothing has ldpi) and xxxhdpi for the newest flagships. Android will automatically look for image assets in the folder corresponding to the current device, and will fallback to the default /drawable folder if it can't find it anywhere else. You might be tempted to avoid creating density-specific versions of all your images/icons, but it's very likely that will lead to performance issues.
iOS Images 101 iOS has a similar approach to Android, but only demands three image scales (1x, 2x, 3x). Instead of using separate folders, iOS expects these files to reside in the same folder (usually /Resources) with suffixes to specify density (image.png, firstname.lastname@example.org, email@example.com). There are no absolute requirements for these images sizes, just make sure your source files are large enough to look sharp on the newest devices. They should be added to the project with the build action for each set to BundleResource.
Note - an alternative approach for managing images in iOS projects is to add them to Catalog Image Sets. This is actually the approach currently recommended by Apple, however, it's very common to continue using the method described above, especially for Xamarin Forms projects. MFractor's image management tools will currently add images using the BundleResource approach.
Xamarin Forms Images 101
Thankfully, Xamarin Forms helps a lot when referencing images from shared code. As long as you name your image files the same in each project, you can simply reference them by that name in C# or XAML with no issues. MFractor will even preview the image for you.
On an Image control, for example, it looks like this:
ImageSource vs. String You may notice that Image.Source is actually of type ImageSource, but we just assigned a string. This is because the property has an TypeConverter associated with it that does the conversion.
While there are times when you may want to create an ImageSource directly (ex. embedded resources, custom caching), generally you can rely on the implicit conversion for local files and uris.
MVVM If you build your app using the MVVM (model-view-viewmodel) pattern, you can rely on the ImageSource type converter by using ViewModel properties of type String and binding to them directly. This is particularly nice if you like to avoid any dependencies on the UI framework (eg. Xamarin Forms) in your ViewModels, which makes them a bit easier to test and reuse.
MFractor Now, after all that, you may be thinking that images are a bit of pain, and I wouldn't disagree. The process of adding just a single new icon to an app can be quite laborious and error-prone when done manually. Thankfully, MFractor Image Import Wizard automates the whole process of resizing, naming, and adding your images to all your projects. It's a great time-saver! You can access the image wizard through the top MFractor menu.
MFractor also provides an Image Manager where you delete existing resources, optimise your image assets using TinyPNG and perform a slew of other useful actions. You can access the image manager through the top MFractor menu and then choosing Manage Image Assets.
This article was written by Ben Reierson (@ben_reierson), a freelance Xamarin developer who tends to be based in Melbourne when he's not doing the whole digital nomad thing. More info for the curious at https://www.linkedin.com/in/