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) でイメージを使用できます。
  • ツール バー項目 - イメージは、イメージ ツールバー項目 () としてツールバー (NSToolbarNSToolbarItem) に追加できます。
  • ソース リスト アイコン - ソース リストの一部として (特別に書式設定された NSOutlineView)。
  • アプリ アイコン - 一連のイメージを 1 つのセットに .icns グループ化し、アプリケーションのアイコンとして使用できます。 詳細については、 アプリケーション アイコン のドキュメントを参照してください。

さらに、macOS には、アプリケーション全体で使用できる定義済みのイメージのセットが用意されています。

An example run of the app

この記事では、Xamarin.Mac アプリケーションでのイメージとアイコンの操作の基本について説明します。 この記事で使用する 主要な概念と手法については、まず Hello Mac の記事、特 に Xcode とインターフェイス ビルダーアウトレットとアクション の概要に関するセクションを参照することを強くお勧めします。

Xamarin.Mac プロジェクトへのイメージの追加

Xamarin.Mac アプリケーションで使用するイメージを追加する場合、開発者がプロジェクトのソースにイメージ ファイルを含めることができる場所と方法がいくつかあります。

  • メイン プロジェクト ツリー [非推奨] - イメージをプロジェクト ツリーに直接追加できます。 メイン プロジェクト ツリーに格納されているイメージをコードから呼び出す場合、フォルダーの場所は指定されません。 (例: NSImage image = NSImage.ImageNamed("tags.png");)。
  • Resources フォルダー [非推奨] - 特殊な Resources フォルダーは、アイコン、起動画面、一般的なイメージ (または開発者が追加するその他のイメージまたはファイル) など、アプリケーションのバンドルの一部となるすべてのファイル用です。 メイン プロジェクト ツリーに格納されているイメージと同様に、リソース フォルダーに格納されているイメージをコードから呼び出す場合、フォルダーの場所は指定されません。 (例: NSImage.ImageNamed("tags.png"))。
  • カスタム フォルダーまたはサブフォルダー [非推奨] - 開発者は、プロジェクトのソース ツリーにカスタム フォルダーを追加し、そこにイメージを格納できます。 ファイルを追加する場所をサブフォルダーに入れ子にして、プロジェクトをさらに整理できます。 たとえば、開発者がプロジェクトにフォルダーを追加し、そのフォルダーにHeartsサブ フォルダーを追加Cardした場合、そのフォルダーにイメージ Jack.pngHearts格納すると、NSImage.ImageNamed("Card/Hearts/Jack.png")実行時にイメージが読み込まれます。
  • アセット カタログ イメージ セット [推奨] - OS X El Capitan で追加されたアセット カタログ イメージ セットには、アプリケーションのさまざまなデバイスとスケール ファクターをサポートするために必要なすべてのバージョンまたはイメージの表現が含まれています。 イメージ アセットのファイル名 (@1x、@2x) に依存する代わりに、

資産カタログ イメージ セットへのイメージの追加

前述のように、アセット カタログ イメージ セットには、アプリケーションのさまざまなデバイスとスケール ファクターをサポートするために必要なすべてのバージョンまたはイメージ表現が含まれています。 イメージ アセットのファイル名 (上記の「解像度に依存しないイメージとイメージ命名法」を参照) に依存するのではなく、イメージ セット はアセット エディターを使用して、どのイメージがどのデバイスや解像度に属するかを指定します。

  1. Solution Pad で Assets.xcassets ファイルをダブルクリックして、編集用に開きます。

    Selecting the Assets.xcassets

  2. アセット リスト右クリックし、[新しいイメージ セット] を選択します。

    Adding a new image set

  3. 新しいイメージ セットを選択すると、エディターが表示されます。

    Selecting the new image set

  4. ここから、必要なさまざまなデバイスと解像度ごとに画像をドラッグできます。

  5. アセット リストで新しいイメージ セットの名前ダブルクリックして編集します。

    Editing the image set name

イメージ セットに追加された特殊な Vector クラス。これにより、PDF 形式のベクターイメージをキャセットに含め、代わりに個々のビットマップ ファイルをさまざまな解像度で含めることができます。 このメソッドを使用すると、@1x解像度 (ベクター PDF ファイルとして書式設定) 用の 1 つのベクター ファイルを指定し、ファイルの@2xバージョンと@3xバージョンがコンパイル時に生成され、アプリケーションのバンドルに含まれます。

The image set editor interface

たとえば、解像度が 150px x 150px のアセット カタログのベクターとしてファイルを含めると MonkeyIcon.pdf 、コンパイル時に、最終的なアプリ バンドルに次のビットマップ アセットが含まれます。

  1. MonkeyIcon@1x.png - 150 x 150px の解像度。
  2. MonkeyIcon@2x.png - 300 x 300px の解像度。
  3. MonkeyIcon@3x.png - 450 x 450px の解像度。

アセット カタログで PDF ベクター イメージを使用する場合は、次の事項を考慮する必要があります。

  • PDF はコンパイル時にビットマップにラスター化され、最終的なアプリケーションに出荷されるビットマップであるため、これは完全なベクター サポートではありません。
  • アセット カタログで設定したイメージのサイズを調整することはできません。 画像のサイズを変更しようとすると (コード内で、または自動レイアウトおよびサイズ クラスを使用して)、他のビットマップと同様にイメージが歪みます。

Xcode のインターフェイス ビルダーでイメージ セット使用する場合は、属性インスペクターのドロップダウン リストからセットの名前を選択するだけです。

Selecting an image set in Xcode's Interface Builder

新しいアセット コレクションの追加

Assets Catalogs でイメージを操作する場合は、Assets.xcassets コレクションにすべてのイメージを追加するのではなく、新しいコレクションを作成する必要がある場合があります。 たとえば、オンデマンド リソースを設計する場合などです。

新しいアセット カタログをプロジェクトに追加するには:

  1. Solution Pad でプロジェクトを右クリックし、[新しいファイルの追加>]を選択します。..

  2. Mac>アセット カタログを選択し、コレクションの名前入力し、[新規] ボタンをクリックします。

    Adding a new Asset Catalog

ここから、プロジェクトに自動的に含まれる既定 の Assets.xcassets コレクションと同じ方法でコレクションを操作できます。

リソースへのイメージの追加

重要

macOS アプリでイメージを操作するこの方法は、Apple によって非推奨になりました。 代わりに、アセット カタログ イメージ セットを使用してアプリのイメージを管理する必要があります。

Xamarin.Mac アプリケーション (C# コードまたは Interface Builder) でイメージ ファイルを使用する前に、プロジェクトの Resources フォルダーにバンドル リソースとして含める必要があります。 プロジェクトにファイルを追加するには、次の操作を行います。

  1. ソリューション パッドでプロジェクトの [リソース] フォルダーを右クリックし、[ファイルの追加>] を選択します。..:

    Adding a file

  2. [ファイルの追加] ダイアログ ボックスで、プロジェクトに追加するイメージ ファイルを選択し、[ビルドのオーバーライド] アクション選択BundleResourceし、[開く] ボタンをクリックします。

    Selecting the files to add

  3. ファイルがまだ [リソース] フォルダーにない場合は、ファイルをコピー、移動またはリンクするかどうかを確認するメッセージが表示されます。 必要に応じて、通常は コピーを選択します。

    Selecting the add action

  4. 新しいファイルがプロジェクトに含まれて、使用するために読み取られます。

    The new image files added to the Solution Pad

  5. 必要なイメージ ファイルに対してこのプロセスを繰り返します。

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

プロジェクトに追加すると、次のように表示されます。

The image files in the Solution Pad

インターフェイス ビルダーで 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 要素の一部として選択できます (画像を処理する場合)。

インターフェイス ビルダーでイメージを使用するには、次の操作を行います。

  1. ビルド アクションBundleResource次のリソース フォルダーにイメージを追加します。

    An image resource in the Solution Pad

  2. Main.storyboard ファイルをダブルクリックして、インターフェイス ビルダーで編集用に開きます。

    Editing the main storyboard

  3. イメージを取り込む UI 要素をデザインサーフェイスにドラッグします (画像ツール バー項目など)。

    Editing a toolbar item

  4. [イメージ名] ドロップダウンで、[リソース] フォルダーに追加したイメージを選択します。

    Selecting an image for a toolbar item

  5. 選択した画像がデザイン画面に表示されます。

    The image being displayed in the Toolbar editor

  6. 変更を保存し、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 アプリの設計に基づいて、配色の変更 (ユーザー設定に基づくなど) に合わせて、ユーザー インターフェイス内のアイコンまたはイメージをカスタマイズする必要がある場合があります。

この効果を実現するには、イメージ アセットのレンダリング モードをテンプレート イメージ切り替えます。

Setting a template image

Xcode のインターフェイス ビルダーから、UI コントロールにイメージアセットを割り当てます。

Selecting an image in Xcode's Interface Builder

または、必要に応じてコードでイメージ ソースを設定します。

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'sGetViewForItemのメソッドによってデータが返される方法を変更して、一般的な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;

出力例:

An example of displaying an image in an app

テーブル ビューの操作の詳細については、テーブル ビューのドキュメントを参照してください。

アウトライン ビューでの画像の使用

セルNSOutlineViewの一部として画像を含めるには、アウトライン ビューNSTableViewDelegate'sGetViewのメソッドによってデータが返される方法を変更して、一般的な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;

出力例:

An example of an image being displayed in an Outline View

アウトライン ビューの操作の詳細については、アウトライン ビューのドキュメントを参照してください。

まとめ

この記事では、Xamarin.Mac アプリケーションでのイメージとアイコンの操作について詳しく説明しました。 さまざまな種類とイメージの使用方法、Xcode のインターフェイス ビルダーでイメージとアイコンを使用する方法、C# コードでイメージとアイコンを操作する方法について説明しました。