カスタム レンダラーの概要

カスタム レンダラーにより、Xamarin.Forms コントロールの外観とビヘイビアーをカスタマイズするための強力な方法が提供されます。 それらは、スタイルに関する小さな変更や、洗練されたプラットフォーム固有のレイアウトおよびビヘイビアーのカスタマイズのために使用できます。 この記事では、カスタム レンダラーの概要を示し、カスタム レンダラーを作成するプロセスについて説明します。

Xamarin.Formsページ、レイアウト、およびコントロールは、 クロスプラットフォーム モバイル ユーザー インターフェイスを記述するための一般的な API を提供します。 各ページ、レイアウトおよびコントロールは、Renderer クラスを使用してプラットフォームごとに異なる方法でレンダリングされます。次に (Xamarin.Forms の処理形式に対応する) ネイティブ コントロールが作成され、画面に配置され、共有コードに指定されたビヘイビアーが追加されます。

開発者は独自の Renderer クラスを実装して、コントロールの外観や動作をカスタマイズできます。 特定の種類のカスタム レンダラーを 1 つのアプリケーション プロジェクトに追加して、ある場所のコントロールをカスタマイズし、さらに他のプラットフォーム上の既定の動作を許可することができます。また、異なるカスタム レンダラーを各アプリケーション プロジェクトに追加して、iOS、Android、ユニバーサル Windows プラットフォーム (UWP) 上で異なる外観を作成することができます。 ただし、カスタム レンダラー クラスを実装してシンプルなコントロールのカスタマイズを実行すると、多くの場合、応答はヘビーウェイトになります。 エフェクトによってこのプロセスは簡略化されます。通常、エフェクトはわずかなスタイルの変更に使用されます。 詳細については、「Effects」 (エフェクト) を参照してください。

カスタム レンダラーが必要な理由の確認

カスタム レンダラーを使用せずに Xamarin.Forms コントロールの外観を変更するには、サブクラス化によってカスタム コントロールを作成し、元のコントロールの代わりにカスタム コントロールを使用するという 2 段階のプロセスがあります。 次のコード例に、Entry コントロールをサブクラス化する例を示します。

public class MyEntry : Entry
{
  public MyEntry ()
  {
    BackgroundColor = Color.Gray;
  }
}

MyEntry コントロールは、BackgroundColor がグレーに設定された Entry コントロールです。参照するには、Xaml でその場所の名前空間を宣言し、コントロール要素の名前空間プレフィックスを使用します。 次のコード例は、ContentPage がどのように MyEntry カスタム コントロールを使用できるかを示しています。

<ContentPage
    ...
    xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
    ...>
    ...
    <local:MyEntry Text="In Shared Code" />
    ...
</ContentPage>

任意の local 名前空間プレフィックスを指定できます。 ただし、namespaceassembly の値は、カスタム コントロールの詳細と一致する必要があります。 名前空間が宣言されると、プレフィックスを使用してカスタム コントロールが参照されます。

注意

xmlns の定義は、共有プロジェクトよりも .NET Standard ライブラリ プロジェクトの方がはるかに簡単です。 .NET Standard ライブラリはアセンブリにコンパイルされるので、assembly=CustomRenderer の値を決定することは簡単です。 共有プロジェクトを使用する場合、すべての共有アセット (XAML を含む) は個々の参照プロジェクトにコンパイルされます。つまり、iOS、Android、および UWP プロジェクトにそれぞれアセンブリ名がある場合、アプリケーションごとに異なる値にする必要があるため、xmlns 宣言を記述することはできません。 共有プロジェクト用の XAML のカスタム コントロールでは、すべてのアプリケーション プロジェクトを同じアセンブリ名を使用して構成する必要があります。

次のスクリーンショットに示すように、MyEntry カスタム コントロールは、各プラットフォームにグレーの背景でレンダリングされます。

各プラットフォームの MyEntry カスタム コントロール

各プラットフォームのコントロールの背景色を変更するには、コントロールをサブクラス化する必要があります。 ただし、プラットフォーム固有の拡張機能やカスタマイズを利用できないため、この手法は実行できるものに限られています。 必要な場合は、カスタム レンダラーを実装する必要があります。

カスタム レンダラー クラスの作成

カスタム レンダラー クラスを作成するプロセスは次のとおりです。

  1. ネイティブ コントロールをレンダリングするレンダラー クラスのサブクラスを作成します。
  2. ネイティブ コントロールをレンダリングするメソッドをオーバーライドして、ロジックを書き込み、コントロールをカスタマイズします。 多くの場合、OnElementChanged メソッドはネイティブ コントロールのレンダリングに使用され、対応する Xamarin.Forms コントロールが作成されるときに呼び出されます。
  3. ExportRenderer 属性をカスタム レンダラー クラスに追加して、Xamarin.Forms コントロールのレンダリングに使用されるように指定します。 この属性は、Xamarin.Forms にカスタム レンダラーを登録するために使用されます。

注意

ほとんどの Xamarin.Forms 要素では、プラットフォーム プロジェクトごとにカスタム レンダラーを指定するかどうかは任意です。 カスタム レンダラーが登録されていない場合は、コントロールの基底クラス用の既定のレンダラーが使用されます。 ただし、View または ViewCell 要素をレンダリングするときは、各プラットフォーム プロジェクトにカスタム レンダラーが必要です。

このシリーズのトピックでは、さまざまな Xamarin.Forms 要素に対するこのプロセスの例を示し、説明します。

トラブルシューティング

ソリューションに追加された .NET Standard ライブラリ プロジェクトにカスタム コントロールが含まれる場合 (つまり、Visual Studio for Mac/Visual Studio Xamarin.Forms アプリ プロジェクト テンプレートで作成された .NET Standard ライブラリではない場合)、カスタム コントロールにアクセスしようとすると、iOS で例外が発生することがあります。 この問題が発生した場合は、AppDelegate クラスからカスタム コントロールへの参照を作成することで解決できます。

var temp = new ClassInPCL(); // in AppDelegate, but temp not used anywhere

これにより、強制的に ClassInPCL 型を解決してコンパイラに認識させることができます。 代わりに、Preserve 属性を AppDelegate クラスに追加して同じ結果を得ることもできます。

[assembly: Preserve (typeof (ClassInPCL))]

これで実行時に必要であることを示す ClassInPCL 型への参照が作成されます。 詳細については、コードの保存に関するページを参照してください。

まとめ

この記事では、カスタム レンダラーの概要を示し、カスタム レンダラーを作成するプロセスについて説明しました。 カスタム レンダラーにより、Xamarin.Forms コントロールの外観とビヘイビアーをカスタマイズするための強力な方法が提供されます。 それらは、スタイルに関する小さな変更や、洗練されたプラットフォーム固有のレイアウトおよびビヘイビアーのカスタマイズのために使用できます。