Images dans Xamarin.Mac

Cet article traite de l’utilisation d’images et d’icônes dans une application Xamarin.Mac. Il décrit la création et la maintenance des images nécessaires pour créer l’icône de votre application et utiliser des images dans le code C# et le Générateur d’interface de Xcode.

Vue d’ensemble

Lorsque vous utilisez C# et .NET dans une application Xamarin.Mac, vous avez accès aux mêmes outils Image et Icônes qu’un développeur travaillant dans Objective-C et Xcode .

Il existe plusieurs façons d’utiliser des ressources d’image à l’intérieur d’une application macOS (anciennement mac OS X). De l’affichage d’une image dans le cadre de l’interface utilisateur de votre application, en l’affectant à un contrôle d’interface utilisateur tel qu’une barre d’outils ou un élément de liste source, à fournir des icônes, Xamarin.Mac facilite l’ajout d’illustrations à vos applications macOS de la manière suivante :

  • Éléments de l’interface utilisateur : les images peuvent être affichées en arrière-plan ou dans le cadre de votre application dans un affichage image (NSImageView).
  • Bouton : les images peuvent être affichées dans des boutons (NSButton).
  • Cellule Image : dans le cadre d’un contrôle basé sur une table (NSTableViewou NSOutlineView), les images peuvent être utilisées dans une cellule Image (NSImageCell).
  • Élément de barre d’outils - Les images peuvent être ajoutées à une barre d’outils (NSToolbar) en tant qu’élément de barre d’outils image (NSToolbarItem).
  • Icône liste source - Dans le cadre d’une liste source (une liste spécialement mise en forme NSOutlineView).
  • Icône d’application : une série d’images peut être regroupée dans un .icns ensemble et utilisée comme icône de votre application. Pour plus d’informations, consultez notre documentation sur l’icône d’application.

En outre, macOS fournit un ensemble d’images prédéfinies qui peuvent être utilisées dans toute votre application.

Exemple d’exécution de l’application

Dans cet article, nous allons aborder les principes de base de l’utilisation d’images et d’icônes dans une application Xamarin.Mac. Il est fortement suggéré que vous travaillez tout d’abord dans l’article Hello, Mac , en particulier les sections Introduction to Xcode and Interface Builder et Outlets and Actions , car elle couvre les concepts et techniques clés que nous utiliserons dans cet article.

Ajout d’images à un projet Xamarin.Mac

Lors de l’ajout d’une image à utiliser dans une application Xamarin.Mac, il existe plusieurs emplacements et méthodes permettant au développeur d’inclure un fichier image à la source du projet :

  • Arborescence de projet principale [déconseillée] : les images peuvent être ajoutées directement à l’arborescence des projets. Lors de l’appel d’images stockées dans l’arborescence du projet principal à partir du code, aucun emplacement de dossier n’est spécifié. Par exemple : NSImage image = NSImage.ImageNamed("tags.png");.
  • Dossier ressources [déconseillé] : le dossier Ressources spéciales concerne tout fichier qui fera partie du bundle de l’application, tel que l’icône, l’écran de lancement ou les images générales (ou tout autre fichier ou image que le développeur souhaite ajouter). Lors de l’appel d’images stockées dans le dossier Ressources à partir du code, comme les images stockées dans l’arborescence du projet principal, aucun emplacement de dossier n’est spécifié. Par exemple : NSImage.ImageNamed("tags.png").
  • Dossier personnalisé ou sous-dossier [déconseillé] : le développeur peut ajouter un dossier personnalisé à l’arborescence source des projets et y stocker les images. L’emplacement où le fichier est ajouté peut être imbriqué dans un sous-dossier pour faciliter l’organisation du projet. Par exemple, si le développeur a ajouté un Card dossier au projet et à un sous-dossier de ce dossier, stockez une image Jack.png dans le Hearts dossier, NSImage.ImageNamed("Card/Hearts/Jack.png") chargerait l’image au moment de Hearts l’exécution.
  • Ensembles d’images de catalogue de ressources [préférés] : ajoutés dans OS X El Capitan, les ensembles d’images catalogues de ressources contiennent toutes les versions ou représentations d’une image nécessaires pour prendre en charge différents appareils et facteurs d’échelle pour votre application. Au lieu de compter sur le nom de fichier des ressources d’image (@1x, @2x).

Ajout d’images à un jeu d’images de catalogue de ressources

Comme indiqué ci-dessus, un ensemble d’images catalogues de ressources contient toutes les versions ou représentations d’une image nécessaires pour prendre en charge différents appareils et facteurs d’échelle pour votre application. Au lieu de compter sur le nom de fichier des ressources d’image (voir les images indépendantes de résolution et la nomenclature d’images ci-dessus), les jeux d’images utilisent l’éditeur de ressources pour spécifier l’image qui appartient à l’appareil et/ou à la résolution.

  1. Dans le Panneau Solution, double-cliquez sur le fichier Assets.xcassets pour l’ouvrir pour modification :

    Sélection des assets.xcassets

  2. Cliquez avec le bouton droit sur la liste des ressources et sélectionnez Nouveau jeu d’images :

    Ajout d’un nouveau jeu d’images

  3. Sélectionnez le nouveau jeu d’images et l’éditeur s’affiche :

    Sélection du nouveau jeu d’images

  4. À partir de là, nous pouvons faire glisser des images pour chacun des différents appareils et résolutions requis.

  5. Double-cliquez sur le nom du nouveau jeu d’images dans la liste des ressources pour le modifier :

    Modification du nom du jeu d’images

Une classe Vector spéciale telle qu’elle a été ajoutée aux jeux d’images qui nous permet d’inclure une image vectorielle au format PDF dans l’ensemble de cassets, y compris des fichiers bitmap individuels aux différentes résolutions. À l’aide de cette méthode, vous fournissez un fichier vectoriel unique pour la résolution @1x (mise en forme en tant que fichier PDF vectoriel) et les versions @2x et @3x du fichier seront générées au moment de la compilation et incluses dans l’ensemble de l’application.

Interface de l’éditeur d’ensemble d’images

Par exemple, si vous incluez un MonkeyIcon.pdf fichier comme vecteur d’un catalogue d’éléments multimédias avec une résolution de 150px x 150px, les ressources bitmap suivantes sont incluses dans le bundle d’applications final lorsqu’il a été compilé :

  1. MonkeyIcon@1x.png - Résolution de 150 px x 150 px.
  2. MonkeyIcon@2x.png - Résolution de 300 px x 300 px.
  3. MonkeyIcon@3x.png - Résolution de 450 px x 450 px.

Les éléments suivants doivent être pris en compte lors de l’utilisation d’images vectorielles PDF dans les catalogues de ressources :

  • Cette prise en charge de vecteurs n’est pas complète, car le fichier PDF sera ratérisé dans une bitmap au moment de la compilation et les bitmaps fournies dans l’application finale.
  • Vous ne pouvez pas ajuster la taille de l’image une fois qu’elle a été définie dans le catalogue de ressources. Si vous tentez de redimensionner l’image (dans le code ou à l’aide de classes de disposition et de taille automatiques), l’image est déformée comme n’importe quelle autre bitmap.

Lorsque vous utilisez un jeu d’images dans le Générateur d’interface de Xcode, vous pouvez simplement sélectionner le nom du jeu dans la liste déroulante de l’inspecteur d’attribut :

Sélection d’un jeu d’images dans le Générateur d’interface de Xcode

Ajout de nouvelles collections de ressources

Lorsque vous travaillez avec des images dans les catalogues de ressources, il peut arriver que vous souhaitiez créer une collection, au lieu d’ajouter toutes vos images à la collection Assets.xcassets . Par exemple, lors de la conception de ressources à la demande.

Pour ajouter un nouveau catalogue de ressources à votre projet :

  1. Cliquez avec le bouton droit sur le projet dans le panneau Solution, puis sélectionnez Ajouter>un nouveau fichier...

  2. Sélectionnez Le catalogue de ressources Mac>, entrez un nom pour la collection, puis cliquez sur le bouton Nouveau :

    Ajout d’un nouveau catalogue de ressources

À partir de là, vous pouvez utiliser la collection de la même façon que la collection Assets.xcassets par défaut incluse automatiquement dans le projet.

Ajout d’images à des ressources

Important

Cette méthode d’utilisation d’images dans une application macOS a été déconseillée par Apple. Vous devez utiliser les jeux d’images du catalogue d’éléments multimédias pour gérer les images de votre application à la place.

Avant de pouvoir utiliser un fichier image dans votre application Xamarin.Mac (dans le code C# ou à partir du Générateur d’interface), il doit être inclus dans le dossier Ressources du projet en tant que ressource groupée. Pour ajouter un fichier à un projet, procédez comme suit :

  1. Cliquez avec le bouton droit sur le dossier Ressources de votre projet dans le panneau Solution, puis sélectionnez Ajouter>des fichiers... :

    Ajout d’un fichier

  2. Dans la boîte de dialogue Ajouter des fichiers, sélectionnez les fichiers d’images à ajouter au projet, sélectionnez BundleResource l’action Remplacer la génération, puis cliquez sur le bouton Ouvrir :

    Sélection des fichiers à ajouter

  3. Si les fichiers ne se trouvent pas déjà dans le dossier Ressources , vous êtes invité à copier, déplacer ou lier les fichiers. Choisissez les éléments qui conviennent à vos besoins, généralement qui seront copiés :

    Sélection de l’action d’ajout

  4. Les nouveaux fichiers seront inclus dans le projet et lus pour une utilisation :

    Nouveaux fichiers image ajoutés au panneau Solution

  5. Répétez le processus pour tous les fichiers image requis.

Vous pouvez utiliser n’importe quel fichier png, jpg ou pdf comme image source dans votre application Xamarin.Mac. Dans la section suivante, nous allons examiner l’ajout de versions haute résolution de nos images et icônes pour prendre en charge les Mac basés sur Retina.

Important

Si vous ajoutez des images au dossier Ressources , vous pouvez laisser l’action remplacer la génération définie sur Default. L’action de génération par défaut pour ce dossier est BundleResource.

Fournir des versions haute résolution de toutes les ressources graphiques d’application

Toute ressource graphique que vous ajoutez à une application Xamarin.Mac (icônes, contrôles personnalisés, curseurs personnalisés, illustrations personnalisées, etc.) doit avoir des versions haute résolution en plus de leurs versions de résolution standard. Cela est nécessaire pour que votre application s’affiche le mieux lorsqu’elle s’exécute sur un ordinateur Mac équipé d’un écran Rétine.

Adopter la convention d’affectation de noms @2x

Important

Cette méthode d’utilisation d’images dans une application macOS a été déconseillée par Apple. Vous devez utiliser les jeux d’images du catalogue d’éléments multimédias pour gérer les images de votre application à la place.

Lorsque vous créez les versions standard et haute résolution d’une image, suivez cette convention d’affectation de noms pour la paire d’images lorsque vous les incluez dans votre projet Xamarin.Mac :

  • Standard-Resolution - ImageName.filename-extension (exemple : tags.png)
  • High-Resolution-extension - ImageName@2x.filename (Exemple : ) tags@2x.png

Lorsqu’ils sont ajoutés à un projet, ils s’affichent comme suit :

Fichiers image dans le Panneau Solution

Lorsqu’une image est affectée à un élément d’interface utilisateur dans Interface Builder, vous sélectionnez simplement le fichier dans ImageName.format d’extension de nom_fichier (exemple : tags.png). La même chose pour l’utilisation d’une image dans le code C#, vous allez choisir le fichier dans ImageName.format d’extension de nom_fichier.

Lorsque vous exécutez l’application Xamarin.Mac sur un Mac, imageName. L’image de format nom_fichier-extension sera utilisée sur les affichages de résolution standard, l’image ImageName@2x.filename-extension sera automatiquement choisie sur les bases d’affichage Rétine Mac.

Utilisation d’images dans Le Générateur d’interface

Toute ressource d’image que vous avez ajoutée au dossier Ressources de votre projet Xamarin.Mac et que vous avez défini l’action de génération sur BundleResource s’affiche automatiquement dans Interface Builder et peut être sélectionnée dans le cadre d’un élément d’interface utilisateur (s’il gère des images).

Pour utiliser une image dans le générateur d’interface, procédez comme suit :

  1. Ajoutez une image au dossier Ressources avec une action de génération de BundleResource:

    Ressource d’image dans le panneau Solution

  2. Double-cliquez sur le fichier Main.storyboard pour l’ouvrir pour modification dans le Générateur d’interface :

    Modification du storyboard principal

  3. Faites glisser un élément d’interface utilisateur qui prend des images sur l’aire de conception (par exemple, un élément de barre d’outils Image) :

    Modification d’un élément de barre d’outils

  4. Sélectionnez l’image que vous avez ajoutée au dossier Ressources dans la liste déroulante Nom de l’image :

    Sélection d’une image pour un élément de barre d’outils

  5. L’image sélectionnée s’affiche dans l’aire de conception :

    Image affichée dans l’éditeur de barre d’outils

  6. Enregistrez vos modifications et revenez à Visual Studio pour Mac à synchroniser avec Xcode.

Les étapes ci-dessus fonctionnent pour n’importe quel élément d’interface utilisateur qui permet à leur propriété image d’être définie dans l’inspecteur d’attribut. Là encore, si vous avez inclus une version @2x de votre fichier image, elle sera automatiquement utilisée sur les Mac basés sur l’affichage Rétine.

Important

Si l’image n’est pas disponible dans la liste déroulante Nom de l’image, fermez votre projet .storyboard dans Xcode et rouvrez-le à partir de Visual Studio pour Mac. Si l’image n’est toujours pas disponible, vérifiez que son action de génération est BundleResource et que l’image a été ajoutée au dossier Ressources .

Utilisation d’images dans le code C#

Lors du chargement d’une image en mémoire à l’aide du code C# dans votre application Xamarin.Mac, l’image est stockée dans un NSImage objet. Si le fichier image a été inclus dans le bundle d’applications Xamarin.Mac (inclus dans les ressources), utilisez le code suivant pour charger l’image :

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

Le code ci-dessus utilise la méthode statique ImageNamed("...") de la NSImage classe pour charger l’image donnée en mémoire à partir du dossier Resources , si l’image est introuvable, null est retournée. Comme les images affectées dans le Générateur d’interface, si vous avez inclus une version @2x de votre fichier image, elle sera automatiquement utilisée sur les Mac basés sur l’affichage Rétine.

Pour charger des images en dehors de l’ensemble de l’application (à partir du système de fichiers Mac), utilisez le code suivant :

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

Utilisation d’images de modèle

En fonction de la conception de votre application macOS, il peut arriver que vous deviez personnaliser une icône ou une image à l’intérieur de l’interface utilisateur pour qu’elle corresponde à une modification du jeu de couleurs (par exemple, en fonction des préférences de l’utilisateur).

Pour atteindre cet effet, basculez le mode de rendu de votre ressource image en image de modèle :

Définition d’une image de modèle

À partir du Générateur d’interface de Xcode, affectez la ressource image à un contrôle d’interface utilisateur :

Sélection d’une image dans le Générateur d’interface de Xcode

Ou si vous le souhaitez, définissez la source d’image dans le code :

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

Ajoutez la fonction publique suivante à votre contrôleur de vue :

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

Important

En particulier avec l’avènement du mode sombre dans macOS Mojave, il est important d’éviter l’API lors de la LockFocus réutilisation d’objets rendus NSImage personnalisés. Ces images deviennent statiques et ne seront pas automatiquement mises à jour pour tenir compte de l’apparence ou de l’affichage des modifications de densité.

En utilisant le mécanisme basé sur le gestionnaire ci-dessus, le re-rendu pour les conditions dynamiques se produit automatiquement lorsque l’hôte NSImage est hébergé, par exemple, dans un NSImageView.

Enfin, pour teinter une image de modèle, appelez cette fonction par rapport à l’image pour coloriser :

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

Utilisation d’images avec des vues de tableau

Pour inclure une image dans le cadre de la cellule d’un NSTableView, vous devez modifier la façon dont les données sont retournées par la méthode de NSTableViewDelegate's GetViewForItem la vue table pour utiliser une NSTableCellView valeur plutôt que la méthode classique NSTextField. Par exemple :

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

Il y a quelques lignes d’intérêt ici. Tout d’abord, pour les colonnes que nous voulons inclure une image, nous créons une nouvelle NSImageView taille et un emplacement requis, nous créons également une nouvelle NSTextField position et placez sa position par défaut selon que nous utilisons ou non une image :

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

Deuxièmement, nous devons inclure le nouveau champ Image View et Text dans le parent NSTableCellView:

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

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

Enfin, nous devons indiquer au champ de texte qu’il peut réduire et croître avec la cellule Table View :

view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;

Exemple de sortie :

Exemple d’affichage d’une image dans une application

Pour plus d’informations sur l’utilisation des vues de table, consultez notre documentation sur les vues de table.

Utilisation d’images avec des vues hiérarchiques

Pour inclure une image dans le cadre de la cellule d’un NSOutlineView, vous devez modifier la façon dont les données sont retournées par la méthode du mode GetView NSTableViewDelegate's Plan pour utiliser une NSTableCellView valeur plutôt que la méthode classiqueNSTextField. Par exemple :

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

Il y a quelques lignes d’intérêt ici. Tout d’abord, pour les colonnes que nous voulons inclure une image, nous créons une nouvelle NSImageView taille et un emplacement requis, nous créons également une nouvelle NSTextField position et placez sa position par défaut selon que nous utilisons ou non une image :

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

Deuxièmement, nous devons inclure le nouveau champ Image View et Text dans le parent NSTableCellView:

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

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

Enfin, nous devons indiquer au champ de texte qu’il peut réduire et croître avec la cellule Table View :

view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;

Exemple de sortie :

Exemple d’image affichée en mode Plan

Pour plus d’informations sur l’utilisation des vues hiérarchiques, consultez notre documentation sur les vues hiérarchiques .

Résumé

Cet article a examiné en détail l’utilisation d’images et d’icônes dans une application Xamarin.Mac. Nous avons vu les différents types et utilisations d’Images, comment utiliser des images et des icônes dans le Générateur d’interface de Xcode et comment utiliser des images et des icônes dans le code C#.