プラットフォーム固有設定

Download Sampleサンプルのダウンロード

プラットフォーム固有設定により、カスタムのレンダラーやエフェクトを実装しなくても、特定のプラットフォームのみで利用できる機能を使用できます。

XAML または fluent コード API を通してプラットフォーム固有設定を使用するプロセスは以下のとおりです。

  1. Xamarin.Forms.PlatformConfiguration 名前空間の xmlns 宣言または using ディレクティブを追加します。
  2. 以下のようにプラットフォーム固有の機能を含む名前空間の xmlns 宣言または using ディレクティブを追加します。
    1. iOS では、これは Xamarin.Forms.PlatformConfiguration.iOSSpecific 名前空間です。
    2. Android では、これは Xamarin.Forms.PlatformConfiguration.AndroidSpecific 名前空間です。 Android AppCompat の場合、これは Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat 名前空間です。
    3. ユニバーサル Windows プラットフォームでは、これは Xamarin.Forms.PlatformConfiguration.WindowsSpecific 名前空間です。
  3. XAML から、または On<T> fluent API を使用したコードからプラットフォーム固有設定を適用します。 T の値には、Xamarin.Forms.PlatformConfiguration 名前空間の iOSAndroidWindows 型のいずれかを指定できます。

Note

プラットフォーム固有設定を、それが利用できないプラットフォーム上で使用しようとしても、エラーは発生しないことに注意してください。 代わりに、コードはプラットフォーム固有設定が適用されない状態で実行されます。

On<T> fluent コード API を通して使用されるプラットフォーム固有設定は IPlatformElementConfiguration オブジェクトを返します。 これにより、メソッド カスケードを使用して同じオブジェクト上で複数のプラットフォーム固有設定を呼び出すことができます。

Xamarin.Forms によって提供されるプラットフォーム固有設定の詳細については、「iOS プラットフォーム固有設定」、「Android プラットフォーム固有設定」、および「Windows プラットフォーム固有設定」を参照してください。

プラットフォーム固有設定の作成

ベンダーは、独自のプラットフォーム固有設定をエフェクトと共に作成できます。 エフェクトは特定の機能を提供するもので、プラットフォーム固有設定を通して公開されます。 その結果、エフェクトは XAML と fluent コード API を通してより簡単に使用できます。

プラットフォーム固有設定の作成プロセスは以下のとおりです。

  1. 特定の機能をエフェクトとして実装します。 詳細については、「エフェクトの作成」を参照してください。
  2. エフェクトを公開するプラットフォーム固有クラスを作成します。 詳細については、「プラットフォーム固有クラスの作成」を参照してください。
  3. プラットフォーム固有クラスで、添付プロパティを実装して、XAML を通してプラットフォーム固有設定を使用できるようにします。 詳細については、「添付プロパティの追加」を参照してください。
  4. プラットフォーム固有クラスで、拡張メソッドを実装して、fluent コード API を通してプラットフォーム固有設定を使用できるようにします。 詳細については、「拡張メソッドの追加」を参照してください。
  5. エフェクトの実装を変更して、エフェクトが適用されるのは、プラットフォーム固有設定がエフェクトと同じプラットフォームで呼び出された場合だけになるようにします。 詳細については、「エフェクトの作成」を参照してください。

プラットフォーム固有設定としてエフェクトを公開する結果、XAML と fluent コード API を通してエフェクトをより簡単に使用できるようになります。

Note

ユーザーによる使用が簡単になるように、ベンダーはこの手法を使用して独自のプラットフォーム固有設定を作成することが想定されています。 ユーザーは独自のプラットフォーム固有設定を作成することもできますが、エフェクトを作成して使用するよりも多くのコードが必要になることに注意する必要があります。

このサンプル アプリケーションは、以下のように Label コントロールによって表示されるテキストに影を追加する Shadow プラットフォーム固有設定を示しています。

Shadow Platform-Specific

このサンプル アプリケーションでは、理解を容易にするために、各プラットフォームでの Shadow プラットフォーム固有設定を実装しています。 ただし、各プラットフォーム固有のエフェクトの実装を別にすると、Shadow クラスの実装は各プラットフォームで大部分は同じです。 したがって、このガイドでは 1 つのプラットフォームでの Shadow クラスの実装および関連するエフェクトに焦点を当てます。

エフェクトの詳細については、「エフェクトを使用したコントロールのカスタマイズ」を参照してください。

プラットフォーム固有クラスの作成

プラットフォーム固有設定は以下のように public static クラスとして作成されます。

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
  public static Shadow
  {
    ...
  }
}

以降のセクションでは、Shadow プラットフォーム固有設定および関連するエフェクトの実装について説明します。

添付プロパティの追加

XAML を通した使用を可能にするためには、以下のように添付プロパティを Shadow プラットフォーム固有設定に追加する必要があります。

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
    using System.Linq;
    using Xamarin.Forms;
    using Xamarin.Forms.PlatformConfiguration;
    using FormsElement = Xamarin.Forms.Label;

    public static class Shadow
    {
        const string EffectName = "MyCompany.LabelShadowEffect";

        public static readonly BindableProperty IsShadowedProperty =
            BindableProperty.CreateAttached("IsShadowed",
                                            typeof(bool),
                                            typeof(Shadow),
                                            false,
                                            propertyChanged: OnIsShadowedPropertyChanged);

        public static bool GetIsShadowed(BindableObject element)
        {
            return (bool)element.GetValue(IsShadowedProperty);
        }

        public static void SetIsShadowed(BindableObject element, bool value)
        {
            element.SetValue(IsShadowedProperty, value);
        }

        ...

        static void OnIsShadowedPropertyChanged(BindableObject element, object oldValue, object newValue)
        {
            if ((bool)newValue)
            {
                AttachEffect(element as FormsElement);
            }
            else
            {
                DetachEffect(element as FormsElement);
            }
        }

        static void AttachEffect(FormsElement element)
        {
            IElementController controller = element;
            if (controller == null || controller.EffectIsAttached(EffectName))
            {
                return;
            }
            element.Effects.Add(Effect.Resolve(EffectName));
        }

        static void DetachEffect(FormsElement element)
        {
            IElementController controller = element;
            if (controller == null || !controller.EffectIsAttached(EffectName))
            {
                return;
            }

            var toRemove = element.Effects.FirstOrDefault(e => e.ResolveId == Effect.Resolve(EffectName).ResolveId);
            if (toRemove != null)
            {
                element.Effects.Remove(toRemove);
            }
        }
    }
}

IsShadowed 添付プロパティは、Shadow クラスがアタッチされるコントロールに MyCompany.LabelShadowEffect エフェクトを追加したり、削除したりするために使用されます。 この添付プロパティは、そのプロパティの値が変更されるときに実行される OnIsShadowedPropertyChanged デリゲートを登録します。 次に、このメソッドは AttachEffect または DetachEffect メソッドを呼び出し、IsShadowed 添付プロパティの値に基づいてエフェクトを追加または削除します。 エフェクトは、コントロールの Effects コレクションを変更することによって、コントロールに追加またはコントロールから削除されます。

Note

エフェクトは、エフェクトの実装で指定された解決グループ名と一意識別子を連結した値を指定することで解決されることに注意してください。 詳細については、「エフェクトの作成」を参照してください。

添付プロパティについて詳しくは、「添付プロパティ」をご覧ください。

拡張メソッドの追加

fluent コード API を通した使用を可能にするには、以下のように拡張メソッドを Shadow プラットフォーム固有設定に追加する必要があります。

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
    using System.Linq;
    using Xamarin.Forms;
    using Xamarin.Forms.PlatformConfiguration;
    using FormsElement = Xamarin.Forms.Label;

    public static class Shadow
    {
        ...
        public static bool IsShadowed(this IPlatformElementConfiguration<iOS, FormsElement> config)
        {
            return GetIsShadowed(config.Element);
        }

        public static IPlatformElementConfiguration<iOS, FormsElement> SetIsShadowed(this IPlatformElementConfiguration<iOS, FormsElement> config, bool value)
        {
            SetIsShadowed(config.Element, value);
            return config;
        }
        ...
    }
}

IsShadowed および SetIsShadowed 拡張メソッドは、それぞれ IsShadowed 添付プロパティの get および set アクセサーを呼び出します。 各拡張メソッドは IPlatformElementConfiguration<iOS, FormsElement> 型に対して機能し、これは iOS の Label インスタンスでそのプラットフォーム固有設定を呼び出すことができることを指定します。

エフェクトの作成

Shadow プラットフォーム固有設定は、MyCompany.LabelShadowEffectLabel に追加し、それを削除します。 iOS プロジェクト用の LabelShadowEffect の実装を次のコード例に示します。

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace ShadowPlatformSpecific.iOS
{
    public class LabelShadowEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            UpdateShadow();
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);

            if (args.PropertyName == Shadow.IsShadowedProperty.PropertyName)
            {
                UpdateShadow();
            }
        }

        void UpdateShadow()
        {
            try
            {
                if (((Label)Element).OnThisPlatform().IsShadowed())
                {
                    Control.Layer.CornerRadius = 5;
                    Control.Layer.ShadowColor = UIColor.Black.CGColor;
                    Control.Layer.ShadowOffset = new CGSize(5, 5);
                    Control.Layer.ShadowOpacity = 1.0f;
                }
                else if (!((Label)Element).OnThisPlatform().IsShadowed())
                {
                    Control.Layer.ShadowOpacity = 0;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

IsShadowed 添付プロパティが true に設定されている場合、かつ Shadow プラットフォーム固有設定がこのエフェクトの実装対象と同じプラットフォームで呼び出された場合に、UpdateShadow メソッドは Control.Layer プロパティを設定して影を作成します。 このチェックは OnThisPlatform メソッドで実行されます。

Shadow.IsShadowed 添付プロパティの値が実行時に変更された場合、エフェクトは影を削除することで応答する必要があります。 したがって、OnElementPropertyChanged メソッドのオーバーライドされたバージョンは、UpdateShadow メソッドを呼び出すことによってバインド可能なプロパティの変更に応答するために使用されます。

エフェクトの作成の詳細については、「エフェクトの作成」および「エフェクト パラメータを添付プロパティとして渡す」を参照してください。

プラットフォーム固有設定の使用

Shadow プラットフォーム固有設定は、以下のように Shadow.IsShadowed 添付プロパティを boolean 値に設定することで XAML で使用されます。

<ContentPage xmlns:ios="clr-namespace:MyCompany.Forms.PlatformConfiguration.iOS" ...>
  ...
  <Label Text="Label Shadow Effect" ios:Shadow.IsShadowed="true" ... />
  ...
</ContentPage>

あるいは、Fluent API を使用して C# から使用することもできます。

using Xamarin.Forms.PlatformConfiguration;
using MyCompany.Forms.PlatformConfiguration.iOS;

...

shadowLabel.On<iOS>().SetIsShadowed(true);