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 (
NSTableView
ouNSOutlineView
), 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.
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 leHearts
dossier,NSImage.ImageNamed("Card/Hearts/Jack.png")
chargerait l’image au moment deHearts
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.
Dans le Panneau Solution, double-cliquez sur le fichier Assets.xcassets pour l’ouvrir pour modification :
Cliquez avec le bouton droit sur la liste des ressources et sélectionnez Nouveau jeu d’images :
Sélectionnez le nouveau jeu d’images et l’éditeur s’affiche :
À partir de là, nous pouvons faire glisser des images pour chacun des différents appareils et résolutions requis.
Double-cliquez sur le nom du nouveau jeu d’images dans la liste des ressources pour le modifier :
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.
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é :
- MonkeyIcon@1x.png - Résolution de 150 px x 150 px.
- MonkeyIcon@2x.png - Résolution de 300 px x 300 px.
- 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 :
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 :
Cliquez avec le bouton droit sur le projet dans le panneau Solution, puis sélectionnez Ajouter>un nouveau fichier...
Sélectionnez Le catalogue de ressources Mac>, entrez un nom pour la collection, puis cliquez sur le bouton Nouveau :
À 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 :
Cliquez avec le bouton droit sur le dossier Ressources de votre projet dans le panneau Solution, puis sélectionnez Ajouter>des fichiers... :
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 :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 :
Les nouveaux fichiers seront inclus dans le projet et lus pour une utilisation :
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 :
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 :
Ajoutez une image au dossier Ressources avec une action de génération de
BundleResource
:Double-cliquez sur le fichier Main.storyboard pour l’ouvrir pour modification dans le Générateur d’interface :
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) :
Sélectionnez l’image que vous avez ajoutée au dossier Ressources dans la liste déroulante Nom de l’image :
L’image sélectionnée s’affiche dans l’aire de conception :
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 :
À partir du Générateur d’interface de Xcode, affectez la ressource image à un contrôle d’interface utilisateur :
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 :
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 :
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#.