Imágenes en Xamarin.Mac

En este artículo se describe cómo trabajar con imágenes e iconos en una aplicación de Xamarin.Mac. Describe la creación y el mantenimiento de las imágenes necesarias para crear el icono de la aplicación y el uso de imágenes tanto en código de C# como en el código de Xcode Interface Builder.

Información general

Al trabajar con C# y .NET en una aplicación de Xamarin.Mac, tiene acceso a las mismas herramientas de imagen e icono que un desarrollador que trabaja en Objective-CObjective-C

Hay varias maneras de usar los recursos de imagen dentro de una aplicación macOS (anteriormente conocida como Mac OS X). Desde mostrar simplemente una imagen como parte de la interfaz de usuario de la aplicación a , asignarla a un control de interfaz de usuario, como una barra de herramientas o un elemento de lista de origen, hasta proporcionar iconos, Xamarin.Mac facilita la adición de excelentes ilustraciones a las aplicaciones macOS de las maneras siguientes:

  • Elementos de la interfaz de usuario: las imágenes se pueden mostrar como fondos o como parte de la aplicación en una vista de imagen ( ).
  • Botón: las imágenes se pueden mostrar en botones ( ).
  • Celda de imagen: como parte de un control basado en tabla ( o ), las imágenes se pueden usar en una celda de imagen ( NSOutlineViewNSImageCell ).
  • Elemento de la barra de herramientas: las imágenes se pueden agregar a una barra de herramientas ( ) como un elemento de la barra de herramientas de imagen ( NSToolbarItem ).
  • Icono de lista de origen: como parte de una lista de origen (con un formato especial).
  • Icono de aplicación: una serie de imágenes se pueden agrupar en un conjunto y usarse como icono de la aplicación. Consulte nuestra documentación del icono de aplicación para obtener más información.

Además, macOS proporciona un conjunto de imágenes predefinidas que se pueden usar en toda la aplicación.

Una ejecución de ejemplo de la aplicación Unaejecución de ejemplo de la

En este artículo, se tratarán los conceptos básicos de trabajar con imágenes e iconos en una aplicación de Xamarin.Mac. Se recomienda encarecidamente trabajar primero en el artículo Hola, Mac, en concreto en las secciones Introducción a Xcode y Interface Builder y Salidas y acciones, ya que trata los conceptos y técnicas clave que se usarán en este artículo.

Adición de imágenes a un proyecto de Xamarin.Mac

Al agregar una imagen para usarla en una aplicación de Xamarin.Mac, hay varios lugares y formas en que el desarrollador puede incluir el archivo de imagen en el origen del proyecto:

  • Árbol de proyecto principal [en desuso]: las imágenes se pueden agregar directamente al árbol de proyectos. Al llamar a imágenes almacenadas en el árbol del proyecto principal desde código, no se especifica ninguna ubicación de carpeta. Por ejemplo: NSImage image = NSImage.ImageNamed("tags.png");.
  • Carpeta De recursos [en desuso]: la carpeta Recursos especial es para cualquier archivo que formará parte del paquete de la aplicación, como icono, pantalla de inicio o imágenes generales (o cualquier otra imagen o archivo que el desarrollador quiera agregar). Al llamar a imágenes almacenadas en la carpeta Recursos desde código, al igual que las imágenes almacenadas en el árbol del proyecto principal, no se especifica ninguna ubicación de carpeta. Por ejemplo: NSImage.ImageNamed("tags.png").
  • Carpeta personalizada o subcarpeta [en desuso]: el desarrollador puede agregar una carpeta personalizada al árbol de origen del proyecto y almacenar allí las imágenes. La ubicación donde se agrega el archivo se puede anidar en una subcarpeta para ayudar a organizar aún más el proyecto. Por ejemplo, si el desarrollador agregó una carpeta al proyecto y una sub carpeta de a esa carpeta, almacenaría una imagenJack.pngen la carpeta , cargaría la imagen en tiempo de CardHeartsCardHeartsNSImage.ImageNamed("Card/Hearts/Jack.png") ejecución.
  • Conjuntos de imágenes del catálogo de recursos [preferido]: agregados en OS X El Capitan, los conjuntos de imágenes de catálogos de recursos contienen todas las versiones o representaciones de una imagen que son necesarias para admitir varios dispositivos y factores de escala para la aplicación. En lugar de confiar en el nombre de archivo de los recursos de imagen (@1x, @2x).

Agregar imágenes a un conjunto de imágenes del catálogo de recursos

Como se indicó anteriormente, los conjuntos de imágenes de catálogos de recursos contienen todas las versiones o representaciones de una imagen que son necesarias para admitir varios dispositivos y factores de escala para la aplicación. En lugar de basarse en el nombre de archivo de los recursos de imagen (consulte la resolución de imágenes independientes y la nomenclatura de imágenes anterior), los conjuntos de imágenes usan el Editor de recursos para especificar qué imagen pertenece a qué dispositivo o resolución.

  1. En la Panel de solución, haga doble clic en el archivo Assets.xcassets para abrirlo para su edición:

    Selección de Assets.xcassets

  2. Haga clic con el botón derecho en la lista De recursos y seleccione Nuevo conjunto de imágenes:

    Agregar un nuevo conjunto de imágenes

  3. Seleccione el nuevo conjunto de imágenes y se mostrará el editor:

    Selección del nuevo conjunto de imágenesSelección del nuevo conjunto de

  4. Desde aquí podemos arrastrar imágenes para cada uno de los distintos dispositivos y resoluciones necesarios.

  5. Haga doble clic en el nombre del nuevo conjunto de imágenes en la lista de recursos para editarlo:

    Edición del nombre del conjunto de imágenes

Una clase Vector especial que se ha agregado a Conjuntos de imágenes que nos permite incluir una imagen de vector con formato PDF en el conjunto de casset en su lugar, incluidos los archivos de mapa de bits individuales en las distintas resoluciones. Con este método, se proporciona un único archivo vectorial para la resolución @1x (con formato de archivo PDF vectorial) y las versiones @2x y @3x del archivo se generarán en tiempo de compilación y se incluirán en el paquete de la aplicación.

Interfaz del editor del conjunto de imágenesLa interfaz del editor del conjunto de

Por ejemplo, si incluye un archivo como vector de un catálogo de recursos con una resolución de MonkeyIcon.pdf 150 px x 150 px, los siguientes recursos de mapa de bits se incluirían en la agrupación de aplicaciones final cuando se compiló:

  1. MonkeyIcon@1x.png - Resolución de 150 px x 150 px.
  2. MonkeyIcon@2x.png - Resolución de 300 px x 300 px.
  3. MonkeyIcon@3x.png - Resolución de 450 px x 450 px.

Al usar imágenes vectoriales PDF en catálogos de recursos, se debe tener en cuenta lo siguiente:

  • Esto no es compatibilidad completa con vectores, ya que el PDF se rasterizará en un mapa de bits en tiempo de compilación y los mapas de bits se enviarán en la aplicación final.
  • No se puede ajustar el tamaño de la imagen una vez que se ha establecido en el catálogo de recursos. Si intenta cambiar el tamaño de la imagen (ya sea en el código o mediante el diseño automático y las clases de tamaño), la imagen se distorsionará igual que cualquier otro mapa de bits.

Al usar un conjunto de imágenes en el Interface Builder de Xcode, simplemente puede seleccionar el nombre del conjunto en la lista desplegable del Inspector de atributos:

Selección de un conjunto de imágenes en lapágina Interface Builder Xcode Selección de un conjunto de imágenes en la página de

Adición de nuevas colecciones de recursos

Al trabajar con imágenes en catálogos de recursos, puede haber ocasiones en las que quiera crear una nueva colección, en lugar de agregar todas las imágenes a la colección Assets.xcassets. Por ejemplo, al diseñar recursos a petición.

Para agregar un nuevo catálogo de recursos al proyecto:

  1. Haga clic con el botón derecho en el proyecto en Panel de solución seleccione Agregarnuevo archivo...

  2. Seleccione Catálogo derecursos deMac, escriba un nombre para la colección y haga clic en el botón Nuevo:

    Agregar un nuevo catálogo de recursos

Desde aquí puede trabajar con la colección de la misma manera que la colección Assets.xcassets predeterminada incluida automáticamente en el proyecto.

Adición de imágenes a recursos

Importante

Apple ha dejado de trabajar con imágenes en una aplicación macOS. En su lugar, debe usar Conjuntos de imágenes del catálogo de recursos para administrador de las imágenes de la aplicación.

Para poder usar un archivo image en la aplicación de Xamarin.Mac (ya sea en código de C# o desde Interface Builder), debe incluirse en la carpeta Resources del proyecto como un recurso de agrupación. Para agregar un archivo a un proyecto, haga lo siguiente:

  1. Haga clic con el botón derecho en la carpeta Recursos del proyecto en la Panel de solución y seleccione Agregaragregar archivos...:

    Agregar un archivo Agregar

  2. En el cuadro de diálogo Agregar archivos, seleccione los archivos de imágenes que desea agregar al proyecto, seleccione para la acción Invalidar compilación y haga clic en el botón Abrir:

    Selección de los archivos que se agregarán

  3. Si los archivos aún no están en la carpeta Recursos, se le preguntará si desea copiar,mover o vincular los archivos. Elija cada una de las que mejor se adapte a sus necesidades, que normalmente será Copiar:

    Selección de la acción agregarSelección de la acción

  4. Los nuevos archivos se incluirán en el proyecto y se leerán para su uso:

    Los nuevos archivos de imagen agregados a la Panel de soluciónLos nuevos archivos

  5. Repita el proceso para los archivos de imagen necesarios.

Puede usar cualquier archivo png, jpg o pdf como imagen de origen en la aplicación Xamarin.Mac. En la siguiente sección, veremos cómo agregar versiones de alta resolución de nuestras imágenes e iconos para admitir macs basados en Retina.

Importante

Si va a agregar imágenes a la carpeta Recursos, puede dejar la acción Invalidar compilación establecida en Predeterminada. La acción de compilación predeterminada para esta carpeta es BundleResource .

Proporcionar versiones de alta resolución de todos los recursos gráficos de la aplicación

Cualquier recurso gráfico que agregue a una aplicación de Xamarin.Mac (iconos, controles personalizados, cursores personalizados, ilustraciones personalizadas, etc.) necesitan tener versiones de alta resolución además de sus versiones de resolución estándar. Esto es necesario para que la aplicación se vea mejor cuando se ejecuta en un equipo Mac equipado con Pantalla de Retina.

Adopción de la @2x de nomenclatura

Importante

Apple ha dejado de trabajar con imágenes en una aplicación macOS. En su lugar, debe usar Conjuntos de imágenes del catálogo de recursos para administrador de las imágenes de la aplicación.

Al crear las versiones estándar y de alta resolución de una imagen, siga esta convención de nomenclatura para el par de imágenes al incluirlas en el proyecto de Xamarin.Mac:

  • Resolución estándarImageName.filename-extension (ejemplo: tags.png)
  • Alta resolución -extension (ejemplo: tags@2x.png )

Cuando se agregan a un proyecto, aparecen de la siguiente manera:

Los archivos de imagen de la Panel de soluciónLos archivos de imagen de la

Cuando una imagen se asigna a un elemento de interfaz de usuario Interface Builder simplemente elegirá el archivo en ImageName.formato de extensión de nombre de archivo (ejemplo: tags.png). Igual que para usar una imagen en código de C#, elegirá el archivo en ImageName.formato de extensión de nombre de archivo.

Cuando la aplicación de Xamarin.Mac se ejecuta en un equipo Mac, imageName.la imagen de formato de extensión de nombre de archivo se usará en las pantallas de resolución estándar; la imagen de extensión se seleccionará automáticamente en macs base display de Retina.

Uso de imágenes en Interface Builder

Cualquier recurso de imagen que haya agregado a la carpeta Resources del proyecto de Xamarin.Mac y que haya establecido la acción de compilación en BundleResource se mostrará automáticamente en Interface Builder y se puede seleccionar como parte de un elemento de interfaz de usuario (si controla imágenes).

Para usar una imagen en el generador de interfaces, haga lo siguiente:

  1. Agregue una imagen a la carpeta Recursos con una acción de compilación de :

    Un recurso de imagen en la Panel de soluciónUn recurso de imagen en el

  2. Haga doble clic en el archivo Main.storyboard para abrirlo para editarlo en Interface Builder:

    Edición del guión gráfico principal

  3. Arrastre un elemento de la interfaz de usuario que toma imágenes a la superficie de diseño (por ejemplo, un elemento de la barra de herramientas de imagen):

    Edición de un elemento de barra de herramientas

  4. Seleccione la imagen que agregó a la carpeta Recursos en la lista desplegable Nombre de la imagen:

    Selección de una imagen para un elemento de barra deherramientas Selección de una imagen para un elemento de barra de

  5. La imagen seleccionada se mostrará en la superficie de diseño:

    Imagen que se muestra en el editor de la barra deherramientas La imagen que se muestra en el editor de la barra de

  6. Guarde los cambios y vuelva a Visual Studio para Mac para sincronizar con Xcode.

Los pasos anteriores funcionan para cualquier elemento de la interfaz de usuario que permita establecer su propiedad de imagen en el Inspector de atributos. De nuevo, si ha incluido una @2x del archivo de imagen, se usará automáticamente en equipos Mac basados en Display de Retina.

Importante

Si la imagen no está disponible en la lista desplegable Nombre de imagen, cierre el proyecto .storyboard en Xcode y vuelva a abrirlo desde Visual Studio para Mac. Si la imagen sigue sin estar disponible, asegúrese de que su acción de compilación es y de que la imagen se ha agregado a la carpeta Recursos.

Uso de imágenes en código de C#

Al cargar una imagen en memoria mediante código de C# en la aplicación de Xamarin.Mac, la imagen se almacenará en un NSImage objeto . Si el archivo de imagen se ha incluido en el paquete de aplicaciones de Xamarin.Mac (incluido en los recursos), use el código siguiente para cargar la imagen:

NSImage image = NSImage.ImageNamed("tags.png");

El código anterior usa el método estático de la clase para cargar la imagen especificada en la memoria desde la carpeta Resources, si no se encuentra ImageNamed("...")NSImage la ImageNamed("...")null imagen, se devolverá. Al igual que las imágenes asignadas en Interface Builder, si ha incluido una versión @2x del archivo de imagen, se usará automáticamente en equipos Mac basados en Display de Retina.

Para cargar imágenes fuera de la agrupación de la aplicación (desde el sistema de archivos Mac), use el código siguiente:

NSImage image = new NSImage("/Users/KMullins/Documents/photo.jpg")

Trabajar con imágenes de plantilla

En función del diseño de la aplicación macOS, puede haber ocasiones en las que necesite personalizar un icono o una imagen dentro del Interfaz de usuario para que coincida con un cambio en la combinación de colores (por ejemplo, en función de las preferencias del usuario).

Para lograr este efecto, cambie el Modo de representación del recurso de imagen a Imagen de plantilla:

Configuración de una imagen de plantillaEstablecimiento de una imagen de

En la página de Interface Builder Xcode, asigne el recurso de imagen a un control de interfaz de usuario:

Selección de una imagen en el Interface Builder XcodeSelección de una imagen en la página

O, opcionalmente, establezca el origen de la imagen en el código:

MyIcon.Image = NSImage.ImageNamed ("MessageIcon");

Agregue la siguiente función pública al controlador de vistas:

public NSImage ImageTintedWithColor(NSImage sourceImage, NSColor tintColor)
    => NSImage.ImageWithSize(sourceImage.Size, false, rect => {
        // Draw the original source image
        sourceImage.DrawInRect(rect, CGRect.Empty, NSCompositingOperation.SourceOver, 1f);

        // Apply tint
        tintColor.Set();
        NSGraphics.RectFill(rect, NSCompositingOperation.SourceAtop);

        return true;
    });

Importante

Especialmente con la llegada del modo oscuro en macOS Mojave, es importante evitar la API al volver a procesar objetos LockFocus representados de forma NSImage personalizada. Estas imágenes se convierten en estáticas y no se actualizarán automáticamente para tener en cuenta los cambios de apariencia o de densidad de pantalla.

Al emplear el mecanismo basado en controlador anterior, la representación de nuevo para condiciones dinámicas se realizará automáticamente cuando se hospeda , por NSImage ejemplo, en NSImageView un .

Por último, para colorear una imagen de plantilla, llame a esta función en la imagen para colorear:

MyIcon.Image = ImageTintedWithColor (MyIcon.Image, NSColor.Red);

Uso de imágenes con vistas de tabla

Para incluir una imagen como parte de la celda en , deberá cambiar la forma en que el método de la vista de tabla devuelve los datos para usar un en lugar del NSTableViewNSTableViewDelegate'sGetViewForItemNSTableCellView típico NSTextField . Por ejemplo:

public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{

    // This pattern allows you reuse existing views when they are no-longer in use.
    // If the returned view is null, you instance up a new view
    // If a non-null view is returned, you modify it enough to reflect the new data
    NSTableCellView view = (NSTableCellView)tableView.MakeView (tableColumn.Title, this);
    if (view == null) {
        view = new NSTableCellView ();
        if (tableColumn.Title == "Product") {
            view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
            view.AddSubview (view.ImageView);
            view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
        } else {
            view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
        }
        view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
        view.AddSubview (view.TextField);
        view.Identifier = tableColumn.Title;
        view.TextField.BackgroundColor = NSColor.Clear;
        view.TextField.Bordered = false;
        view.TextField.Selectable = false;
        view.TextField.Editable = true;

        view.TextField.EditingEnded += (sender, e) => {

            // Take action based on type
            switch(view.Identifier) {
            case "Product":
                DataSource.Products [(int)view.TextField.Tag].Title = view.TextField.StringValue;
                break;
            case "Details":
                DataSource.Products [(int)view.TextField.Tag].Description = view.TextField.StringValue;
                break; 
            }
        };
    }

    // Tag view
    view.TextField.Tag = row;

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.ImageView.Image = NSImage.ImageNamed ("tags.png");
        view.TextField.StringValue = DataSource.Products [(int)row].Title;
        break;
    case "Details":
        view.TextField.StringValue = DataSource.Products [(int)row].Description;
        break;
    }

    return view;
}

Hay algunas líneas de interés aquí. En primer lugar, para las columnas que queremos incluir una imagen, creamos una nueva del tamaño y la ubicación necesarios, también creamos una nueva y colocamos su posición predeterminada en función de si se usa o no una NSImageViewNSTextField imagen:

if (tableColumn.Title == "Product") {
    view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
    view.AddSubview (view.ImageView);
    view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
} else {
    view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
}

En segundo lugar, es necesario incluir la nueva vista de imagen y el campo de texto en el elemento primario NSTableCellView :

view.AddSubview (view.ImageView);
...

view.AddSubview (view.TextField);
...

Por último, es necesario decir al campo de texto que puede reducirse y crecer con la celda de vista de tabla:

view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;

Salida de ejemplo:

Un ejemplo de visualización de una imagen en una aplicación Unejemplo de visualización de una imagen en una

Para obtener más información sobre cómo trabajar con vistas de tabla, consulte nuestra documentación de vistas de tabla.

Uso de imágenes con vistas de esquema

Para incluir una imagen como parte de la celda en , deberá cambiar la forma en que el método de la vista esquema devuelve los datos para usar un en lugar del NSOutlineViewNSTableViewDelegate'sGetViewNSTableCellView típico NSTextField . Por ejemplo:

public override NSView GetView (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item) {
    // Cast item
    var product = item as Product;

    // This pattern allows you reuse existing views when they are no-longer in use.
    // If the returned view is null, you instance up a new view
    // If a non-null view is returned, you modify it enough to reflect the new data
    NSTableCellView view = (NSTableCellView)outlineView.MakeView (tableColumn.Title, this);
    if (view == null) {
        view = new NSTableCellView ();
        if (tableColumn.Title == "Product") {
            view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
            view.AddSubview (view.ImageView);
            view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
        } else {
            view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
        }
        view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
        view.AddSubview (view.TextField);
        view.Identifier = tableColumn.Title;
        view.TextField.BackgroundColor = NSColor.Clear;
        view.TextField.Bordered = false;
        view.TextField.Selectable = false;
        view.TextField.Editable = !product.IsProductGroup;
    }

    // Tag view
    view.TextField.Tag = outlineView.RowForItem (item);

    // Allow for edit
    view.TextField.EditingEnded += (sender, e) => {

        // Grab product
        var prod = outlineView.ItemAtRow(view.Tag) as Product;

        // Take action based on type
        switch(view.Identifier) {
        case "Product":
            prod.Title = view.TextField.StringValue;
            break;
        case "Details":
            prod.Description = view.TextField.StringValue;
            break; 
        }
    };

    // Setup view based on the column selected
    switch (tableColumn.Title) {
    case "Product":
        view.ImageView.Image = NSImage.ImageNamed (product.IsProductGroup ? "tags.png" : "tag.png");
        view.TextField.StringValue = product.Title;
        break;
    case "Details":
        view.TextField.StringValue = product.Description;
        break;
    }

    return view;
}

Hay algunas líneas de interés aquí. En primer lugar, para las columnas que queremos incluir una imagen, creamos una nueva del tamaño y la ubicación necesarios, también creamos una nueva y colocamos su posición predeterminada en función de si se usa o no una NSImageViewNSTextField imagen:

if (tableColumn.Title == "Product") {
    view.ImageView = new NSImageView (new CGRect (0, 0, 16, 16));
    view.AddSubview (view.ImageView);
    view.TextField = new NSTextField (new CGRect (20, 0, 400, 16));
} else {
    view.TextField = new NSTextField (new CGRect (0, 0, 400, 16));
}

En segundo lugar, es necesario incluir la nueva vista de imagen y el campo de texto en el elemento primario NSTableCellView :

view.AddSubview (view.ImageView);
...

view.AddSubview (view.TextField);
...

Por último, es necesario decir al campo de texto que puede reducirse y crecer con la celda de vista de tabla:

view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;

Salida de ejemplo:

Un ejemplo de una imagen que se muestra en una vista esquemaUn ejemplo de una imagen que se muestra en una vista

Para obtener más información sobre cómo trabajar con vistas de esquema, consulte nuestra documentación de vistas de esquema.

Resumen

En este artículo se ha detallado cómo trabajar con imágenes e iconos en una aplicación de Xamarin.Mac. Hemos visto los distintos tipos y usos de imágenes, cómo usar imágenes e iconos en el Interface Builder de Xcode y cómo trabajar con imágenes e iconos en código de C#.