Imágenes en Xamarin.Forms

Download SampleDescargar el ejemplo

Las imágenes se pueden compartir entre plataformas con Xamarin.Forms, se pueden cargar específicamente para cada plataforma o se pueden descargar para su visualización.

Las imágenes son una parte crucial de la navegación, la facilidad de usa y la imagen de marca de las aplicaciones. Xamarin.Forms Las aplicaciones deben poder compartir imágenes en todas las plataformas, pero también pueden mostrar imágenes diferentes en cada plataforma.

También se necesitan imágenes específicas de cada plataforma para los iconos y las pantallas de presentación, que deben configurarse para cada plataforma.

Mostrar imágenes

Xamarin.Forms usa la vista Image para mostrar imágenes en una página. Tiene varias propiedades importantes:

  • Source - Una instancia de ImageSource, ya sea Archivo, Uri o Recurso, que establece la imagen a mostrar.
  • Aspect: cómo ajustar el tamaño de la imagen dentro de los límites en los que se muestra (ya sea para estirar, recortar o aplicar formato letterbox).

Las instancias de ImageSource se pueden obtener mediante métodos estáticos para cada tipo de origen de imagen:

  • FromFile: requiere un nombre de archivo o una ruta de acceso de archivo que se pueda resolver en cada plataforma.
  • FromUri: requiere un objeto URI, por ejemplo, new Uri("http://server.com/image.jpg").
  • FromResource : requiere un identificador de recurso en un archivo de imagen insertado en la aplicación o en el proyecto de biblioteca de .NET Standard, con una acción de compilación:EmbeddedResource.
  • FromStream: requiere una secuencia que proporciona datos de imagen.

La propiedad Aspect determina cómo se escalará la imagen para ajustarse al área de visualización:

  • Fill: ajusta la imagen para rellenar completa y exactamente el área de visualización. Esto puede distorsionar la imagen.
  • AspectFill : recorta la imagen para que rellene el área de visualización al tiempo que conserva el aspecto (es decir, sin distorsión).
  • AspectFit: aplica el formato letterbox a la imagen (si es necesario) para que toda la imagen quepa en el área de visualización, con un espacio en blanco agregado a la parte superior o inferior o a los laterales, en función de si la imagen es ancha o alta.

Las imágenes se pueden cargar desde un archivo local, un recurso incrustado, descargado o cargado desde una secuencia. Además, la vista Image puede mostrar iconos de fuentes especificando los datos de los iconos de fuentes en un objeto FontImageSource. Para obtener más información, vea Mostrar iconos de fuente en la guía Fuentes.

Imágenes locales

Es posible agregar archivos de imagen a cada proyecto de aplicación y hacer referencia a ellos desde código compartido de Xamarin.Forms. Este método de distribución de imágenes es necesario cuando las imágenes son específicas de la plataforma, por ejemplo, al usar resoluciones diferentes en plataformas diversas, o bien al emplear diseños que difieren ligeramente.

Para usar una imagen única en todas las aplicaciones, es necesario usar el mismo nombre de archivo en todas las plataformas. Debe ser un nombre de recurso de Android válido, es decir, solo se permiten letras minúsculas, números, el carácter de subrayado y el punto.

  • iOS: la forma preferida de administrar y admitir imágenes desde iOS 9 es utilizar conjuntos de imágenes del catálogo de activos, que deben contener todas las versiones de una imagen que sean necesarias para admitir varios dispositivos y factores de escala para una aplicación. Para obtener más información, vea Agregar imágenes a un conjunto de imágenes del catálogo de recursos.
  • Android: coloque las imágenes en el directorio Resources/drawable con la acción de compilación: AndroidResource. También se pueden suministrar versiones con valores altos y bajos de PPP de una imagen (en subdirectorios apropiadamente denominados Resources como drawable-ldpi, drawable-hdpi, y drawable-xhdpi).
  • Plataforma universal de Windows (UWP): de forma predeterminada, las imágenes deben colocarse en el directorio raíz de la aplicación con la acción de compilación: Content. Como alternativa, las imágenes se pueden colocar en un directorio diferente que, a continuación, se especifica con una plataforma específica. Para obtener más información, consulte Directorio de imágenes predeterminado en Windows.

Importante

Antes de iOS 9, las imágenes se colocaban normalmente en la carpeta Resources con la acción de compilación: BundleResource. Sin embargo, Apple ha dejado de usar este método para trabajar con imágenes en una aplicación iOS. Para obtener más información, vea Tamaños de imagen y nombres de archivo.

La adhesión a estas reglas de nomenclatura y colocación de archivos permite que el siguiente XAML cargue y muestre la imagen en todas las plataformas:

<Image Source="waterfront.jpg" />

El código de C# equivalente es el siguiente:

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

Las capturas de pantalla siguientes muestran el resultado de mostrar una imagen local en cada plataforma:

Sample application displaying a local image

Para obtener más flexibilidad, la propiedad Device.RuntimePlatform se puede usar para seleccionar un archivo o ruta de acceso de imagen diferente para algunas de las plataformas o todas ellas, como se muestra en este ejemplo de código:

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

Importante

Para usar el mismo nombre de archivo de imagen en todas las plataformas, el nombre debe ser válido en todas las plataformas. Los recursos Drawable de Android tienen restricciones de nomenclatura (solo se permiten letras minúsculas, números, caracteres de subrayado y punto) y, para la compatibilidad multiplataforma, esto debe seguirse también en el resto de plataformas. El nombre de archivo de ejemplo waterfront.png sigue las normas, pero algunos ejemplos de nombres de archivo no válidos son "water front.png", "WaterFront.png", "water-front.png" y "wåterfront.png".

Resoluciones nativas (retina y valores altos de PPP)

iOS, Android y UWP incluyen compatibilidad con diferentes resoluciones de imágenes, donde el sistema operativo elige la imagen adecuada en el entorno de ejecución en función de las funcionalidades del dispositivo. Xamarin.Forms utiliza las API de las plataformas nativas para cargar imágenes locales, por lo que admite automáticamente resoluciones alternativas si los archivos se nombran y ubican correctamente en el proyecto.

La forma preferida de administrar las imágenes desde iOS 9 es arrastrar las imágenes para cada resolución requerida al conjunto de imágenes del catálogo de activos correspondiente. Para obtener más información, vea Agregar imágenes a un conjunto de imágenes del catálogo de recursos.

Antes de iOS 9, las versiones retina de la imagen podían colocarse en la carpeta Resources; dos y tres veces la resolución con un sufijo @2x o @3x en el nombre del archivo antes de la extensión del archivo (por ejemplo, myimage@2x.png). Sin embargo, Apple ha dejado de usar este método para trabajar con imágenes en una aplicación iOS. Para obtener más información, vea Tamaños de imagen y nombres de archivo.

Las imágenes de resolución alternativa de Android deben colocarse en directorios con nombres especiales en el proyecto Android, como se muestra en la siguiente captura de pantalla:

Android multiple-resolution image location

Los nombres de archivo de imagen UWP pueden llevar el sufijo .scale-xxx antes de la extensión de archivo, donde xxx es el porcentaje de escalado aplicado al recurso, por ejemplo myimage.scale-200.png. A continuación, se puede hacer referencia a imágenes en código o XAML sin el modificador de escala, por ejemplo, simplemente myimage.png. La plataforma seleccionará la escala de recursos más cercana adecuada en función del PPP actual de la pantalla.

Controles adicionales que muestran imágenes

Algunos controles tienen propiedades que muestran una imagen, como:

  • Button tiene una propiedad ImageSource que se puede establecer en una imagen de mapa de bits que se va a mostrar en Button. Para obtener más información, consulte Uso de mapas de bits con botones.

  • ImageButton tiene una propiedad Source que se puede establecer en la imagen que se va a mostrar en ImageButton. Para obtener más información, vea Establecimiento del origen de la imagen.

  • ToolbarItem tiene una propiedad IconImageSource que se puede establecer en una imagen que se carga desde un archivo, un recurso incrustado, un URI o una secuencia.

  • ImageCell tiene una propiedad ImageSource que se puede establecer en una imagen recuperada de un archivo, un recurso incrustado, un URI o una secuencia.

  • Page. Cualquier tipo de página que se derive de Page tiene propiedades IconImageSource y BackgroundImageSource, que se pueden asignar a un archivo, un recurso incrustado, un URI o una secuencia. En determinadas circunstancias, como cuando un NavigationPage está mostrando un ContentPage, se mostrará el icono si la plataforma lo admite.

    Importante

    En iOS, la propiedad Page.IconImageSource no se puede rellenar desde una imagen de un conjunto de imágenes de catálogo de recursos. En su lugar, cargue imágenes de icono para la propiedad Page.IconImageSource desde un archivo, recurso incrustado, URI o secuencia.

Imágenes incrustadas

Las imágenes incrustadas también se incluyen con una aplicación (como imágenes locales), pero en lugar de tener una copia de la imagen en la estructura de archivos de cada aplicación, el archivo de imagen se incrusta en el ensamblado como un recurso. Este método de distribución de imágenes se recomienda cuando se usan imágenes idénticas en cada plataforma y es especialmente adecuado para crear componentes, ya que la imagen se agrupa con el código.

Para insertar una imagen en un proyecto, haga clic con el botón derecho para agregar nuevos elementos y seleccione las imágenes que desea agregar. De forma predeterminada, la imagen tendrá Acción de compilación: None; debe establecerse en Acción de compilación: EmbeddedResource.

Set build action to embedded resource

La acción de compilación puede verse y cambiarse en la ventana Propiedades de un archivo.

En este ejemplo, el identificador de recurso es WorkingWithImages.beach.jpg. El IDE ha generado este valor predeterminado mediante la concatenación del espacio de nombres predeterminado para este proyecto con el nombre de archivo, utilizando un punto (.) entre cada valor.

Si coloca imágenes incrustadas en carpetas dentro del proyecto, los nombres de carpeta también se separan por puntos (.) en el identificador de recurso. Mover la imagen beach.jpg a una carpeta denominada MyImages daría lugar a un identificador de recurso de WorkingWithImages.MyImages.beach.jpg.

El código para cargar una imagen incrustada simplemente pasa el identificador de recurso al método ImageSource.FromResource, como se muestra a continuación:

Image embeddedImage = new Image
{
    Source = ImageSource.FromResource("WorkingWithImages.beach.jpg", typeof(MyClass).GetTypeInfo().Assembly)
};

Nota:

Para admitir la visualización de imágenes incrustadas en modo de versión en la Plataforma universal de Windows, es necesario usar la sobrecarga de ImageSource.FromResource que especifica el ensamblado de origen en el que buscar la imagen.

Actualmente no hay ninguna conversión implícita para los identificadores de recursos. En su lugar, debe usar ImageSource.FromResource o new ResourceImageSource() para cargar imágenes incrustadas.

Las capturas de pantalla siguientes muestran el resultado de mostrar una imagen insertada en cada plataforma:

Sample application displaying an embedded image

XAML

Dado que no hay ningún convertidor de tipos integrado de string a ResourceImageSource, XAML no puede cargar de forma nativa estos tipos de imágenes. En su lugar, se puede escribir una extensión de marcado XAML personalizada sencilla para cargar imágenes mediante un identificador de recurso especificado en XAML:

[ContentProperty (nameof(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, typeof(ImageResourceExtension).GetTypeInfo().Assembly);

   return imageSource;
 }
}

Nota:

Para admitir la visualización de imágenes incrustadas en modo de versión en la Plataforma universal de Windows, es necesario usar la sobrecarga de ImageSource.FromResource que especifica el ensamblado de origen en el que buscar la imagen.

Para usar esta extensión, agregue un xmlns personalizado al XAML mediante el espacio de nombres y los valores de ensamblado correctos para el proyecto. A continuación, el origen de la imagen se puede establecer con esta sintaxis: {local:ImageResource WorkingWithImages.beach.jpg}. A continuación se muestra un ejemplo completo de XAML:

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

Solución de problemas de imágenes insertadas

Depurar código

Como a veces es difícil comprender por qué no se carga un recurso específico, puede agregarse de forma temporal el siguiente código de depuración a una aplicación para ayudar a confirmar que los recursos se han configurado correctamente. En la consola se mostrarán todos los recursos incrustados conocidos en el ensamblado específico para ayudar a depurar los problemas de carga de recursos.

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

Imágenes insertadas en otros proyectos

De forma predeterminada, el método ImageSource.FromResource solo busca imágenes en el mismo ensamblado que el código que llama al método ImageSource.FromResource. Con el código de depuración anterior, puede determinar qué ensamblados contienen un recurso específico cambiando la instrucción typeof() por una Type que se sabe que está en cada ensamblado.

Sin embargo, el ensamblado de origen en el que se busca una imagen insertada puede especificarse como argumento del método ImageSource.FromResource:

var imageSource = ImageSource.FromResource("filename.png",
            typeof(MyClass).GetTypeInfo().Assembly);

Descargar imágenes

Las imágenes se pueden descargar automáticamente para mostrarse, como se muestra en el código XAML siguiente:

<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://aka.ms/campus.jpg" />
    <Label Text="campus.jpg gets downloaded from microsoft.com" />
  </StackLayout>
</ContentPage>

El código de C# equivalente es el siguiente:

var webImage = new Image {
     Source = ImageSource.FromUri(
        new Uri("https://aka.ms/campus.jpg")
     ) };

El método ImageSource.FromUri requiere un objeto Uri y devuelve un nuevo UriImageSource que lee de Uri.

También hay una conversión implícita para las cadenas de URI, por lo que el ejemplo siguiente también funcionará:

webImage.Source = "https://aka.ms/campus.jpg";

Las capturas de pantalla siguientes muestran el resultado de mostrar una imagen remota en cada plataforma:

Sample application displaying a downloaded image

Almacenamiento en caché de imágenes descargadas

UriImageSource también admite el almacenamiento en caché de imágenes descargadas, configuradas a través de las siguientes propiedades:

  • CachingEnabled: indica si el almacenamiento en caché está habilitado (true de forma predeterminada).
  • CacheValidity: un TimeSpan que define cuánto tiempo se almacenará la imagen localmente.

El almacenamiento en caché está habilitado de forma predeterminada y almacenará la imagen localmente durante 24 horas. Para deshabilitar el almacenamiento en caché de una imagen determinada, cree una instancia del origen de la imagen de la siguiente manera:

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

Para establecer un período de caché específico (por ejemplo, 5 días) cree una instancia del origen de la imagen de la siguiente manera:

webImage.Source = new UriImageSource
{
    Uri = new Uri("https://aka.ms/campus.jpg"),
    CachingEnabled = true,
    CacheValidity = new TimeSpan(5,0,0,0)
};

El almacenamiento en caché integrado facilita la compatibilidad con situaciones como el desplazamiento de listas de imágenes, en las que se puede establecer (o vincular) una imagen en cada celda y dejar que la caché integrada se encargue de volver a cargar la imagen cuando la celda se desplace de nuevo a la vista.

GIF animado

Xamarin.Forms incluye compatibilidad para mostrar GIF pequeños y animados. Esto se logra estableciendo la propiedad Image.Source en un archivo GIF animado:

<Image Source="demo.gif" />

Importante

Aunque la compatibilidad con GIF animado en Xamarin.Forms incluye la capacidad de descargar archivos, no admite el almacenamiento en caché ni el streaming de GIF animados.

De forma predeterminada, cuando se carga un GIF animado, no se reproducirá. Esto se debe a que la propiedad IsAnimationPlaying, que controla si un GIF animado se está reproduciendo o detenido, tiene un valor predeterminado de false. Esta propiedad, de tipo bool, está respaldada por un objeto BindableProperty, lo que significa que se le puede aplicar estilo y ser el destino de los enlaces de datos.

Por lo tanto, cuando se carga un GIF animado, no se reproducirá hasta que la propiedad IsAnimationPlaying esté establecida en true. La reproducción se puede detener estableciendo la propiedad IsAnimationPlaying en false. Ten en cuenta que esta propiedad no tiene ningún efecto al mostrar un origen de imagen no GIF.

Nota:

En Android, la compatibilidad con GIF animado requiere que la aplicación use representadores rápidos y no funcionará si ha optado por usar los representadores heredados. En UWP, la compatibilidad con GIF animado requiere una versión mínima de la actualización de aniversario de Windows 10 (versión 1607).

Iconos y pantallas de presentación

Aunque no está relacionado con la vista Image, los iconos de aplicaciones y las pantallas de inicio también son un uso importante de las imágenes en los proyectos Xamarin.Forms.

La configuración de iconos y pantallas de inicio para aplicaciones Xamarin.Forms se realiza en cada uno de los proyectos de aplicación. Esto significa generar imágenes de tamaño correcto para iOS, Android y UWP. Estas imágenes deben nombrarse y ubicarse según los requisitos de cada plataforma.

Iconos

Consulte Trabajo con imágenes de iOS, Iconografía de Google y Directrices de UWP para los recursos de mosaico e icono para obtener más información sobre la creación de estos recursos de aplicación.

Además, la vista Image puede mostrar iconos de fuentes especificando los datos de los iconos de fuentes en un objeto FontImageSource. Para obtener más información, vea Mostrar iconos de fuente en la guía Fuentes.

Pantallas de presentación

Solo las aplicaciones de iOS y UWP requieren una pantalla de presentación (también denominada pantalla de inicio o imagen predeterminada).

Consulte la documentación de Trabajo con imágenes de iOS y Pantallas de presentación en el centro de desarrollo de Windows.