Xamarin.Mac のイメージ
この記事は、Xamarin.Mac アプリケーションの画像とアイコンの操作について説明しています。 ここでは、アプリケーションのアイコンを作成するために必要なイメージの作成とメイン、C# コードと Xcode の Interface Builder の両方でイメージを使用する方法について説明します。
概要
Xamarin.Mac アプリケーションで C# と .NET を使用する場合は、開発者が作業しているのと Xcode と同じ Image および Icon ツールにObjective-Cアクセスできます。
macOS (旧称 Mac OS X) アプリケーション内でイメージアセットを使用する方法はいくつかあります。 単にアプリケーションの UI の一部として画像を表示したり、ツール バーやソース リスト項目などの UI コントロールに割り当てたり、アイコンを提供したりすることまで、Xamarin.Mac では、次の方法で macOS アプリケーションに優れたアートワークを簡単に追加できます。
- UI 要素 - イメージは、背景として、またはアプリケーションの一部としてイメージ ビュー (
NSImageView
) に表示できます。 - ボタン - 画像はボタン (
NSButton
) に表示できます。 - Image Cell - テーブル ベースのコントロール (
NSTableView
またはNSOutlineView
) の一部として、Image セル (NSImageCell
) でイメージを使用できます。 - ツール バー項目 - イメージは、イメージ ツールバー項目 () としてツールバー (
NSToolbar
NSToolbarItem
) に追加できます。 - ソース リスト アイコン - ソース リストの一部として (特別に書式設定された
NSOutlineView
)。 - アプリ アイコン - 一連のイメージを 1 つのセットに
.icns
グループ化し、アプリケーションのアイコンとして使用できます。 詳細については、 アプリケーション アイコン のドキュメントを参照してください。
さらに、macOS には、アプリケーション全体で使用できる定義済みのイメージのセットが用意されています。
この記事では、Xamarin.Mac アプリケーションでのイメージとアイコンの操作の基本について説明します。 この記事で使用する 主要な概念と手法については、まず Hello Mac の記事、特 に Xcode とインターフェイス ビルダー と アウトレットとアクション の概要に関するセクションを参照することを強くお勧めします。
Xamarin.Mac プロジェクトへのイメージの追加
Xamarin.Mac アプリケーションで使用するイメージを追加する場合、開発者がプロジェクトのソースにイメージ ファイルを含めることができる場所と方法がいくつかあります。
- メイン プロジェクト ツリー [非推奨] - イメージをプロジェクト ツリーに直接追加できます。 メイン プロジェクト ツリーに格納されているイメージをコードから呼び出す場合、フォルダーの場所は指定されません。 (例:
NSImage image = NSImage.ImageNamed("tags.png");
)。 - Resources フォルダー [非推奨] - 特殊な Resources フォルダーは、アイコン、起動画面、一般的なイメージ (または開発者が追加するその他のイメージまたはファイル) など、アプリケーションのバンドルの一部となるすべてのファイル用です。 メイン プロジェクト ツリーに格納されているイメージと同様に、リソース フォルダーに格納されているイメージをコードから呼び出す場合、フォルダーの場所は指定されません。 (例:
NSImage.ImageNamed("tags.png")
)。 - カスタム フォルダーまたはサブフォルダー [非推奨] - 開発者は、プロジェクトのソース ツリーにカスタム フォルダーを追加し、そこにイメージを格納できます。 ファイルを追加する場所をサブフォルダーに入れ子にして、プロジェクトをさらに整理できます。 たとえば、開発者がプロジェクトにフォルダーを追加し、そのフォルダーに
Hearts
サブ フォルダーを追加Card
した場合、そのフォルダーにイメージ Jack.pngをHearts
格納すると、NSImage.ImageNamed("Card/Hearts/Jack.png")
実行時にイメージが読み込まれます。 - アセット カタログ イメージ セット [推奨] - OS X El Capitan で追加されたアセット カタログ イメージ セットには、アプリケーションのさまざまなデバイスとスケール ファクターをサポートするために必要なすべてのバージョンまたはイメージの表現が含まれています。 イメージ アセットのファイル名 (@1x、@2x) に依存する代わりに、
資産カタログ イメージ セットへのイメージの追加
前述のように、アセット カタログ イメージ セットには、アプリケーションのさまざまなデバイスとスケール ファクターをサポートするために必要なすべてのバージョンまたはイメージ表現が含まれています。 イメージ アセットのファイル名 (上記の「解像度に依存しないイメージとイメージ命名法」を参照) に依存するのではなく、イメージ セット はアセット エディターを使用して、どのイメージがどのデバイスや解像度に属するかを指定します。
Solution Pad で Assets.xcassets ファイルをダブルクリックして、編集用に開きます。
アセット リストを右クリックし、[新しいイメージ セット] を選択します。
新しいイメージ セットを選択すると、エディターが表示されます。
ここから、必要なさまざまなデバイスと解像度ごとに画像をドラッグできます。
アセット リストで新しいイメージ セットの名前をダブルクリックして編集します。
イメージ セットに追加された特殊な Vector クラス。これにより、PDF 形式のベクターイメージをキャセットに含め、代わりに個々のビットマップ ファイルをさまざまな解像度で含めることができます。 このメソッドを使用すると、@1x解像度 (ベクター PDF ファイルとして書式設定) 用の 1 つのベクター ファイルを指定し、ファイルの@2xバージョンと@3xバージョンがコンパイル時に生成され、アプリケーションのバンドルに含まれます。
たとえば、解像度が 150px x 150px のアセット カタログのベクターとしてファイルを含めると MonkeyIcon.pdf
、コンパイル時に、最終的なアプリ バンドルに次のビットマップ アセットが含まれます。
- MonkeyIcon@1x.png - 150 x 150px の解像度。
- MonkeyIcon@2x.png - 300 x 300px の解像度。
- MonkeyIcon@3x.png - 450 x 450px の解像度。
アセット カタログで PDF ベクター イメージを使用する場合は、次の事項を考慮する必要があります。
- PDF はコンパイル時にビットマップにラスター化され、最終的なアプリケーションに出荷されるビットマップであるため、これは完全なベクター サポートではありません。
- アセット カタログで設定したイメージのサイズを調整することはできません。 画像のサイズを変更しようとすると (コード内で、または自動レイアウトおよびサイズ クラスを使用して)、他のビットマップと同様にイメージが歪みます。
Xcode のインターフェイス ビルダーでイメージ セットを使用する場合は、属性インスペクターのドロップダウン リストからセットの名前を選択するだけです。
新しいアセット コレクションの追加
Assets Catalogs でイメージを操作する場合は、Assets.xcassets コレクションにすべてのイメージを追加するのではなく、新しいコレクションを作成する必要がある場合があります。 たとえば、オンデマンド リソースを設計する場合などです。
新しいアセット カタログをプロジェクトに追加するには:
Solution Pad でプロジェクトを右クリックし、[新しいファイルの追加>]を選択します。..
Mac>アセット カタログを選択し、コレクションの名前を入力し、[新規] ボタンをクリックします。
ここから、プロジェクトに自動的に含まれる既定 の Assets.xcassets コレクションと同じ方法でコレクションを操作できます。
リソースへのイメージの追加
重要
macOS アプリでイメージを操作するこの方法は、Apple によって非推奨になりました。 代わりに、アセット カタログ イメージ セットを使用してアプリのイメージを管理する必要があります。
Xamarin.Mac アプリケーション (C# コードまたは Interface Builder) でイメージ ファイルを使用する前に、プロジェクトの Resources フォルダーにバンドル リソースとして含める必要があります。 プロジェクトにファイルを追加するには、次の操作を行います。
ソリューション パッドでプロジェクトの [リソース] フォルダーを右クリックし、[ファイルの追加>] を選択します。..:
[ファイルの追加] ダイアログ ボックスで、プロジェクトに追加するイメージ ファイルを選択し、[ビルドのオーバーライド] アクションを選択
BundleResource
し、[開く] ボタンをクリックします。ファイルがまだ [リソース] フォルダーにない場合は、ファイルをコピー、移動、またはリンクするかどうかを確認するメッセージが表示されます。 必要に応じて、通常は コピーを選択します。
新しいファイルがプロジェクトに含まれて、使用するために読み取られます。
必要なイメージ ファイルに対してこのプロセスを繰り返します。
Xamarin.Mac アプリケーションでは、任意の png、jpg、または pdf ファイルをソース イメージとして使用できます。 次のセクションでは、画像とアイコンの高解像度バージョンを追加して、Retina ベースの Mac をサポートする方法について説明します。
重要
[リソース] フォルダーにイメージを追加する場合は、[ビルドのオーバーライド] アクションを [既定] に設定したままにすることができます。 このフォルダーの既定のビルド アクションは .BundleResource
すべてのアプリ グラフィックス リソースの高解像度バージョンを提供する
Xamarin.Mac アプリケーションに追加するグラフィック アセット (アイコン、カスタム コントロール、カスタム カーソル、カスタム アートワークなど) には、標準解像度バージョンに加えて高解像度バージョンが必要です。 これは、お使いのアプリケーションが網膜ディスプレイ搭載のMacコンピュータ上で実行したときに最高の外観になるように必要です。
@2x名前付け規則を採用する
重要
macOS アプリでイメージを操作するこの方法は、Apple によって非推奨になりました。 代わりに、アセット カタログ イメージ セットを使用してアプリのイメージを管理する必要があります。
イメージの標準バージョンと高解像度バージョンを作成するときは、Xamarin.Mac プロジェクトにイメージ ペアを含めるときに、イメージ ペアの次の名前付け規則に従います。
- Standard-Resolution - ImageName.filename-extension (例: tags.png)
- - ImageName@2x.filename高解像度拡張機能 (例: ) tags@2x.png
プロジェクトに追加すると、次のように表示されます。
インターフェイス ビルダーで UI 要素にイメージが割り当てられている場合は、ImageName でファイルを選択するだけです。filename-extension 形式 (例: tags.png)。 C# コードでイメージを使用する場合と同じように、ImageName でファイルを選択します。filename-extension 形式。
Xamarin.Mac アプリケーションを Mac 上で実行すると、 ImageName になります。filename-extension フォーマットイメージは標準解像度ディスプレイで使用され、 ImageName@2x.filename-extension イメージは自動的にRetinaディスプレイベースのMac上で選択されます。
インターフェイス ビルダーでのイメージの使用
Xamarin.Mac プロジェクトの Resources フォルダーに追加し、ビルド アクションを BundleResource に設定したイメージ リソースは、インターフェイス ビルダーに自動的に表示され、UI 要素の一部として選択できます (画像を処理する場合)。
インターフェイス ビルダーでイメージを使用するには、次の操作を行います。
ビルド アクション
BundleResource
が次のリソース フォルダーにイメージを追加します。Main.storyboard ファイルをダブルクリックして、インターフェイス ビルダーで編集用に開きます。
イメージを取り込む UI 要素をデザインサーフェイスにドラッグします (画像ツール バー項目など)。
[イメージ名] ドロップダウンで、[リソース] フォルダーに追加したイメージを選択します。
選択した画像がデザイン画面に表示されます。
変更を保存し、Visual Studio for Mac に戻って Xcode と同期します。
上記の手順は、属性インスペクターでイメージ プロパティを設定できる UI 要素に対して機能します。 ここでも、画像ファイルの@2xバージョンを含める場合は、自動的にRetinaディスプレイベースのMac上で使用されます。
重要
[Image Name]\(イメージ名\) ドロップダウンでイメージを使用できない場合は、Xcode で .storyboard プロジェクトを閉じて、Visual Studio for Mac から再度開きます。 イメージがまだ使用できない場合は、そのビルド アクションと、イメージがBundleResource
リソース フォルダーに追加されていることを確認します。
C# コードでのイメージの使用
Xamarin.Mac アプリケーションで C# コードを使用してイメージをメモリに読み込むと、イメージはオブジェクトに NSImage
格納されます。 イメージ ファイルが Xamarin.Mac アプリケーション バンドル (リソースに含まれている) に含まれている場合は、次のコードを使用してイメージを読み込みます。
NSImage image = NSImage.ImageNamed("tags.png");
上記のコードでは、クラスの静的ImageNamed("...")
メソッドをNSImage
使用して、指定されたイメージを Resources フォルダーからメモリに読み込みます。イメージが見つからない場合は、null
返されます。 インターフェイスビルダーで割り当てられた画像と同様に、画像ファイルの@2xバージョンを含めた場合は、自動的にRetinaディスプレイベースのMacで使用されます。
アプリケーションのバンドルの外部 (Mac ファイル システムから) イメージを読み込むには、次のコードを使用します。
NSImage image = new NSImage("/Users/KMullins/Documents/photo.jpg")
テンプレート イメージの操作
macOS アプリの設計に基づいて、配色の変更 (ユーザー設定に基づくなど) に合わせて、ユーザー インターフェイス内のアイコンまたはイメージをカスタマイズする必要がある場合があります。
この効果を実現するには、イメージ アセットのレンダリング モードをテンプレート イメージに切り替えます。
Xcode のインターフェイス ビルダーから、UI コントロールにイメージアセットを割り当てます。
または、必要に応じてコードでイメージ ソースを設定します。
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 でダーク モードが出現する場合は、カスタムレンダリングされたNSImage
オブジェクトをLockFocus
再送するときに API を回避することが重要です。 このような画像は静的になり、外観や表示密度の変更を考慮して自動的に更新されることはありません。
上記のハンドラーベースのメカニズムを採用することで、動的条件の再レンダリングは、ホストされている場合NSImage
に自動的に発生します。たとえば、NSImageView
最後に、テンプレート イメージを濃淡化するには、イメージに対してこの関数を呼び出して色付けします。
MyIcon.Image = ImageTintedWithColor (MyIcon.Image, NSColor.Red);
テーブル ビューでのイメージの使用
セルNSTableView
の一部として画像を含めるには、テーブル ビューNSTableViewDelegate's
GetViewForItem
のメソッドによってデータが返される方法を変更して、一般的なNSTextField
代わりに a NSTableCellView
を使用する必要があります。 次に例を示します。
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
のメソッドによってデータが返される方法を変更して、一般的なNSTextField
代わりに a NSTableCellView
を使用する必要があります。 次に例を示します。
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# コードでイメージとアイコンを操作する方法について説明しました。