Изображения в Xamarin.Mac
В этой статье рассматривается работа с изображениями и значками в приложении Xamarin.Mac. В нем описывается создание и обслуживание изображений, необходимых для создания значка приложения и использования изображений в коде C# и конструкторе интерфейсов Xcode.
Обзор
При работе с C# и .NET в приложении Xamarin.Mac у вас есть доступ к тем же средствам изображения и значка, в которых работает Objective-C разработчик, и Xcode .
Существует несколько способов использования ресурсов образа в приложении macOS (прежнее название — Mac OS X). От простого отображения изображения в пользовательском интерфейсе приложения, назначая его элементу управления пользовательского интерфейса, например панели инструментов или элементу списка источников, для предоставления значков Xamarin.Mac упрощает добавление большого рисунка в приложения macOS следующими способами:
- Элементы пользовательского интерфейса — изображения могут отображаться в качестве фона или в составе приложения в представлении изображений (
NSImageView
). - Кнопка — изображения можно отображать в кнопках (
NSButton
). - Ячейка изображения — как часть элемента управления на основе таблицы (
NSTableView
илиNSOutlineView
), изображения можно использовать в ячейке изображения (NSImageCell
). - Элемент панели инструментов — изображения можно добавить на панель инструментов (
NSToolbar
) как элемент панели инструментов изображения (NSToolbarItem
). - Значок исходного списка — в составе исходного списка (специально отформатированный
NSOutlineView
). - Значок приложения — ряд изображений можно сгруппировать в
.icns
набор и использовать в качестве значка приложения. Дополнительные сведения см. в документации по значку приложения.
Кроме того, macOS предоставляет набор предопределенных образов, которые можно использовать во всем приложении.
В этой статье мы рассмотрим основы работы с изображениями и значками в приложении Xamarin.Mac. Настоятельно рекомендуется сначала ознакомиться со статьей Hello, Mac , в частности в разделах "Введение в Xcode" и "Конструктор интерфейсов" и "Торговых точек" и "Действия ", поскольку рассматриваются основные понятия и методы, которые мы будем использовать в этой статье.
Добавление изображений в проект Xamarin.Mac
При добавлении образа для использования в приложении Xamarin.Mac есть несколько мест и способов, которым разработчик может включить файл образа в источник проекта:
- Основное дерево проекта [не рекомендуется] — изображения можно добавлять непосредственно в дерево проектов. При вызове изображений, хранящихся в дереве основного проекта из кода, расположение папки не указано. Например:
NSImage image = NSImage.ImageNamed("tags.png");
. - Папка ресурсов [не рекомендуется] — специальная папка ресурсов предназначена для любого файла, который станет частью пакета приложения, такого как значок, экран запуска или общие изображения (или любой другой образ или файл, который разработчик хочет добавить). При вызове образов, хранящихся в папке resources из кода, так же, как и образы, хранящиеся в основном дереве проекта, расположение папки не указано. Например:
NSImage.ImageNamed("tags.png")
. - Пользовательская папка или вложенные папки [не рекомендуется] — разработчик может добавить пользовательскую папку в дерево источника проектов и сохранить изображения там. Расположение, в котором добавляется файл, можно вложить в вложенную папку, чтобы помочь упорядочить проект. Например, если разработчик добавил
Card
папку в проект и вложенную папкуHearts
этой папки, сохраните изображение Jack.png в папке,NSImage.ImageNamed("Card/Hearts/Jack.png")
загрузит образ воHearts
время выполнения. - Наборы образов каталога активов [предпочтительный] — добавлены в OS X El Capitan, наборы образов каталогов активов содержат все версии или представления образа, необходимые для поддержки различных устройств и коэффициентов масштабирования для приложения. Вместо использования имени файла ресурсов образа (@1x, @2x).
Добавление изображений в набор образов каталога активов
Как упоминалось выше, наборы образов каталогов активов содержат все версии или представления образа, необходимые для поддержки различных устройств и коэффициентов масштабирования для приложения. Вместо того чтобы полагаться на имя файла ресурсов изображения (см. раздел "Независимые изображения разрешения" и "Nomenclature выше"), наборы изображений используют редактор ресурсов, чтобы указать, какой образ принадлежит устройству и /или разрешению.
На панели решения дважды щелкните файл Assets.xcassets, чтобы открыть его для редактирования:
Щелкните правой кнопкой мыши список ресурсов и выберите новый набор изображений:
Выберите новый набор изображений и откроется редактор:
Здесь можно перетащить изображения для каждого из различных устройств и разрешений.
Дважды щелкните имя нового набора изображений в списке ресурсов, чтобы изменить его:
Специальный класс Vector, добавленный в наборы изображений, который позволяет включать форматированный вектор PDF в набор, а не включать отдельные растровые файлы в разных разрешениях. Используя этот метод, вы предоставляете один векторный файл для разрешения @1x (отформатированный как векторНЫЙ PDF-файл), а @2x и @3x версии файла будут создаваться во время компиляции и включаться в пакет приложения.
Например, если вы включаете MonkeyIcon.pdf
файл в качестве вектора каталога активов с разрешением 150px x 150px, следующие растровые ресурсы будут включены в окончательный пакет приложений при компиляции:
- MonkeyIcon@1x.png — разрешение 150 пикселей x 150px.
- MonkeyIcon@2x.png — разрешение 300 пикселей x 300px.
- MonkeyIcon@3x.png — разрешение 450 пикселей x 450px.
При использовании векторных изображений PDF в каталогах активов следует учитывать следующее:
- Это не полная поддержка вектора, так как PDF-файл будет растеризирован на растровое изображение во время компиляции и точечные изображения, отправленные в окончательном приложении.
- Невозможно изменить размер изображения после его установки в каталоге активов. Если вы пытаетесь изменить размер изображения (в коде или с помощью классов автоматического макета и размера), изображение будет искажено так же, как и любое другое растровое изображение.
При использовании набора изображений в построителе интерфейсов Xcode можно просто выбрать имя набора из раскрывающегося списка в инспекторе атрибутов:
Добавление новых коллекций ресурсов
При работе с изображениями в каталогах ресурсов может возникнуть время, когда требуется создать новую коллекцию, а не добавлять все изображения в коллекцию Assets.xcassets . Например, при проектировании ресурсов по запросу.
Чтобы добавить новый каталог активов в проект, выполните приведенные далее действия.
Щелкните проект правой кнопкой мыши на панели решения и выберите "Добавить>новый файл" ...
Выберите каталог активов Mac>, введите имя коллекции и нажмите кнопку "Создать".
Здесь вы можете работать с коллекцией так же, как и коллекция assets.xcassets по умолчанию, автоматически включенная в проект.
Добавление изображений в ресурсы
Внимание
Этот метод работы с изображениями в приложении macOS не рекомендуется apple. Вместо этого следует использовать наборы образов каталога активов для управления изображениями приложения.
Прежде чем использовать файл изображения в приложении Xamarin.Mac (в коде C# или в построителе интерфейсов), его необходимо включить в папку ресурсов проекта в качестве ресурса пакета. Чтобы добавить файл в проект, сделайте следующее:
Щелкните правой кнопкой мыши папку "Ресурсы " в проекте на панели решения и выберите "Добавить>файлы..."
В диалоговом окне "Добавить файлы файлов" выберите файлы изображений, которые нужно добавить в проект, выберите
BundleResource
действие "Переопределить сборку" и нажмите кнопку "Открыть":Если файлы еще не находятся в папке ресурсов, вам будет предложено скопировать, переместить или связать файлы. Выберите все ваши потребности, как правило, это будет Копировать:
Новые файлы будут включены в проект и прочитаны для использования:
Повторите процесс для всех необходимых файлов изображений.
В приложении Xamarin.Mac можно использовать любой png, jpg или pdf-файл в качестве исходного изображения. В следующем разделе мы рассмотрим добавление версий изображений и значков с высоким разрешением для поддержки Mac на основе Сетчатки.
Внимание
Если вы добавляете изображения в папку "Ресурсы" , можно оставить действие "Переопределение сборки" значение Default. Действие сборки по умолчанию для этой папки BundleResource
.
Предоставление версий с высоким разрешением всех графических ресурсов приложения
Любой графический ресурс, добавляемый в приложение Xamarin.Mac (значки, пользовательские элементы управления, настраиваемые курсоры, пользовательские рисунки и т. д.), должен иметь версии высокого разрешения в дополнение к их версиям стандартного разрешения. Это необходимо, чтобы приложение выглядело лучше всего при запуске на компьютере Mac с дисплеем Retina.
Принятие соглашения об именовании @2x
Внимание
Этот метод работы с изображениями в приложении macOS не рекомендуется apple. Вместо этого следует использовать наборы образов каталога активов для управления изображениями приложения.
При создании стандартных и высокоуровневых версий образа следуйте этому соглашению об именовании пары образов при их включении в проект Xamarin.Mac:
- Расширение ImageName.filename (пример: tags.png) -
- Расширение High-Resolution - ImageName@2x.filename (пример: ) tags@2x.png
При добавлении в проект они будут отображаться следующим образом:
Когда изображение назначается элементу пользовательского интерфейса в Конструкторе интерфейсов, вы просто выберете файл в ImageName.Формат расширения filename (пример: tags.png). То же самое для использования изображения в коде C#, вы выберете файл в ImageName.Формат расширения filename.
При запуске приложения Xamarin.Mac на компьютере Mac имя образа.Изображение формата расширения имени файла будет использоваться в стандартных дисплеях разрешения, ImageName@2x.filenameизображение -extension будет автоматически выбрано на базах дисплея Retina Mac.
Использование изображений в построителе интерфейсов
Любой ресурс изображения, добавленный в папку Resources в проекте Xamarin.Mac, и установите действие сборки в BundleResource автоматически отображается в конструкторе интерфейсов и может быть выбран в составе элемента пользовательского интерфейса (если он обрабатывает изображения).
Чтобы использовать образ в построителе интерфейсов, сделайте следующее:
Добавьте изображение в папку "Ресурсы" с действием
BundleResource
сборки:Дважды щелкните файл Main.storyboard , чтобы открыть его для редактирования в Конструкторе интерфейсов:
Перетащите элемент пользовательского интерфейса, который принимает изображения в область конструктора (например, элемент панели инструментов изображения):
Выберите изображение, добавленное в папку "Ресурсы " в раскрывающемся списке "Имя образа":
Выбранный образ будет отображаться в области конструктора:
Сохраните изменения и вернитесь к Visual Studio для Mac для синхронизации с Xcode.
Приведенные выше действия работают для любого элемента пользовательского интерфейса, который позволяет задать свойство изображения в инспекторе атрибутов. Опять же, если вы включили @2x версию файла изображения, он будет автоматически использоваться в Macs на основе retina Display.
Внимание
Если изображение недоступно в раскрывающемся списке "Имя образа", закройте проект раскадровки в Xcode и снова откройте его из Visual Studio для Mac. Если изображение по-прежнему недоступно, убедитесь, что его действие BundleResource
сборки и что изображение было добавлено в папку Resources .
Использование изображений в коде C#
При загрузке образа в память с помощью кода C# в приложении Xamarin.Mac образ будет храниться в объекте NSImage
. Если файл изображения был включен в пакет приложений Xamarin.Mac (включенный в ресурсы), используйте следующий код для загрузки образа:
NSImage image = NSImage.ImageNamed("tags.png");
Приведенный выше код использует статический ImageNamed("...")
метод класса для загрузки заданного NSImage
изображения в память из папки Resources , если изображение не удается найти, null
будет возвращено. Как и изображения, назначенные в построителе интерфейсов, если вы включили @2x версию файла изображения, он будет автоматически использоваться в Mac на основе дисплея Сетчатки.
Чтобы загрузить образы вне пакета приложения (из файловой системы Mac), используйте следующий код:
NSImage image = new NSImage("/Users/KMullins/Documents/photo.jpg")
Работа с образами шаблонов
На основе дизайна приложения macOS может возникнуть время, когда необходимо настроить значок или изображение внутри пользовательского интерфейса, чтобы соответствовать изменению цветовой схемы (например, на основе предпочтений пользователя).
Чтобы добиться этого эффекта, переключите режим отрисовки ресурса изображения на образ шаблона:
В построителе интерфейсов Xcode назначьте ресурс изображения элементу управления пользовательского интерфейса:
Или при необходимости задайте источник изображения в коде:
MyIcon.Image = NSImage.ImageNamed ("MessageIcon");
Добавьте следующую общедоступную функцию в контроллер представления:
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;
});
Внимание
Особенно с появлением темного режима в macOS Mojave важно избежать LockFocus
API при повторной отрисовке NSImage
пользовательских объектов. Такие изображения становятся статическими и не будут автоматически обновляться для учета изменений внешнего вида или отображения плотности.
Используя приведенный выше механизм на основе обработчика, повторная отрисовка динамических условий будет происходить автоматически при NSImage
размещении, например в объекте NSImageView
.
Наконец, чтобы оттенить изображение шаблона, вызовите эту функцию для цвета изображения:
MyIcon.Image = ImageTintedWithColor (MyIcon.Image, NSColor.Red);
Использование изображений с представлениями таблиц
Чтобы включить изображение в ячейку в NSTableView
ячейку, необходимо изменить способ возврата данных методом представления NSTableViewDelegate's
GetViewForItem
таблицы, чтобы использовать NSTableCellView
вместо типичных NSTextField
. Например:
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;
}
Здесь есть несколько линий интереса. Во-первых, для столбцов, которые мы хотим включить изображение, мы создадим новый NSImageView
требуемый размер и расположение, мы также создадим новое NSTextField
и поместим его положение по умолчанию на основе того, используется ли изображение:
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));
}
Во-вторых, необходимо включить новое представление изображения и текстовое поле в родительский NSTableCellView
элемент:
view.AddSubview (view.ImageView);
...
view.AddSubview (view.TextField);
...
Наконец, необходимо сообщить текстовому полю, что он может сжиматься и расти с помощью ячейки представления таблицы:
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
Пример результата:
Дополнительные сведения о работе с представлениями таблиц см. в документации по представлениям таблиц.
Использование изображений с представлениями структуры
Чтобы включить изображение в ячейку в NSOutlineView
ячейку, необходимо изменить способ возврата данных методом "Представление структуры NSTableViewDelegate's
GetView
" вместо NSTableCellView
типичного NSTextField
. Например:
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;
}
Здесь есть несколько линий интереса. Во-первых, для столбцов, которые мы хотим включить изображение, мы создадим новый NSImageView
требуемый размер и расположение, мы также создадим новое NSTextField
и поместим его положение по умолчанию на основе того, используется ли изображение:
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));
}
Во-вторых, необходимо включить новое представление изображения и текстовое поле в родительский NSTableCellView
элемент:
view.AddSubview (view.ImageView);
...
view.AddSubview (view.TextField);
...
Наконец, необходимо сообщить текстовому полю, что он может сжиматься и расти с помощью ячейки представления таблицы:
view.TextField.AutoresizingMask = NSViewResizingMask.WidthSizable;
Пример результата:
Дополнительные сведения о работе с представлениями структуры см. в документации по представлениям структуры.
Итоги
В этой статье подробно рассматривается работа с изображениями и значками в приложении Xamarin.Mac. Мы видели различные типы и использование изображений, как использовать изображения и значки в построителе интерфейсов Xcode и как работать с изображениями и значками в коде C#.