共通言語ランタイム プロパティとして効果のパラメーターを渡す
共通言語ランタイム (CLR) プロパティは、実行時のプロパティの変更に応答しないエフェクトのパラメーターの定義に使用できます。 この記事では、CLR プロパティを使用してエフェクトにパラメーターを渡す方法について説明します。
実行時のプロパティの変更に応答しないエフェクトのパラメーターを作成するプロセスは、次のとおりです。
RoutingEffect
クラスをサブクラス化するpublic
クラスを作成します。RoutingEffect
クラスは、通常はプラットフォーム固有となる内部のエフェクトをラップするプラットフォームに依存しないエフェクトを表します。- 解決グループ名と、各プラットフォーム固有のエフェクトクラスで指定された一意の ID を連結したものを渡して、基底クラス コンストラクターを呼び出すコンストラクターを作成します。
- エフェクトに渡す各パラメーターのクラスにプロパティを追加します。
効果をインスタンス化するときに各プロパティの値を指定することで、パラメーターを効果に渡すことができます。
このサンプル アプリケーションは、Label
コントロールによって表示されるテキストに影を追加する ShadowEffect
を示しています。 次の図に、サンプル アプリケーション内の各プロジェクトの役割と、それらの関係を示します。
HomePage
上の Label
コントロールが、各プラットフォーム固有のプロジェクト内の LabelShadowEffect
によってカスタマイズされます。 パラメーターは ShadowEffect
クラス内のプロパティを介して各 LabelShadowEffect
に渡されます。 各プラットフォームの PlatformEffect
クラスから、各 LabelShadowEffect
クラスが派生します。 これにより、次のスクリーンショットに示すように、Label
コントロールによって表示されるテキストに影が追加されます。
エフェクトのパラメーターを作成する
次のコード例に示すように、エフェクトのパラメーターを表すには、RoutingEffect
クラスをサブクラス化する public
クラスを作成する必要があります。
public class ShadowEffect : RoutingEffect
{
public float Radius { get; set; }
public Color Color { get; set; }
public float DistanceX { get; set; }
public float DistanceY { get; set; }
public ShadowEffect () : base ("MyCompany.LabelShadowEffect")
{
}
}
ShadowEffect
には、各プラットフォーム固有の LabelShadowEffect
に渡されるパラメーターを表す 4 つのプロパティが含まれています。 クラス コンストラクターから基底クラスのコンストラクターが呼び出され、解像度グループ名と、各プラットフォーム固有のエフェクト クラスで指定された一意の ID を連結したもので構成されるパラメーターが渡されます。 そのため、ShadowEffect
がインスタンス化されると、MyCompany.LabelShadowEffect
の新しいインスタンスがコントロールの Effects
コレクションに追加されます。
エフェクトの使用
ShadowEffect
がアタッチされている Label
コントロールを次の XAML コード例に示します。
<Label Text="Label Shadow Effect" ...>
<Label.Effects>
<local:ShadowEffect Radius="5" DistanceX="5" DistanceY="5">
<local:ShadowEffect.Color>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="Black" />
<On Platform="Android" Value="White" />
<On Platform="UWP" Value="Red" />
</OnPlatform>
</local:ShadowEffect.Color>
</local:ShadowEffect>
</Label.Effects>
</Label>
C# での同等の Label
を次のコード例に示します。
var label = new Label {
Text = "Label Shadow Effect",
...
};
Color color = Color.Default;
switch (Device.RuntimePlatform)
{
case Device.iOS:
color = Color.Black;
break;
case Device.Android:
color = Color.White;
break;
case Device.UWP:
color = Color.Red;
break;
}
label.Effects.Add (new ShadowEffect {
Radius = 5,
Color = color,
DistanceX = 5,
DistanceY = 5
});
どちらのコード例でも、ShadowEffect
クラスのインスタンスは、各プロパティに指定された値でインスタンス化されてから、コントロールの Effects
コレクションに追加されます。 ShadowEffect.Color
プロパティにはプラットフォーム固有の色の値が使用されることに注意してください。 詳しくは、「Device Class」(デバイス クラス) をご覧ください。
各プラットフォームでのエフェクトの作成
次のセクションで、LabelShadowEffect
クラスのプラットフォーム固有の実装について説明します。
iOS プロジェクト
iOS プロジェクト用の LabelShadowEffect
の実装を次のコード例に示します。
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.iOS
{
public class LabelShadowEffect : PlatformEffect
{
protected override void OnAttached ()
{
try {
var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
if (effect != null) {
Control.Layer.ShadowRadius = effect.Radius;
Control.Layer.ShadowColor = effect.Color.ToCGColor ();
Control.Layer.ShadowOffset = new CGSize (effect.DistanceX, effect.DistanceY);
Control.Layer.ShadowOpacity = 1.0f;
}
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
}
}
OnAttached
メソッドで ShadowEffect
インスタンスを取得し、指定されたプロパティ値に Control.Layer
プロパティを設定して影を作成します。 エフェクトがアタッチされているコントロールに Control.Layer
プロパティがない場合に備えて、この機能が try
/catch
ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached
メソッドによる実装は提供されません。
Android プロジェクト
Android プロジェクト用の LabelShadowEffect
の実装を次のコード例に示します。
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.Droid
{
public class LabelShadowEffect : PlatformEffect
{
protected override void OnAttached ()
{
try {
var control = Control as Android.Widget.TextView;
var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
if (effect != null) {
float radius = effect.Radius;
float distanceX = effect.DistanceX;
float distanceY = effect.DistanceY;
Android.Graphics.Color color = effect.Color.ToAndroid ();
control.SetShadowLayer (radius, distanceX, distanceY, color);
}
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
}
}
OnAttached
メソッドで ShadowEffect
インスタンスを取得し、指定されたプロパティ値を使用して TextView.SetShadowLayer
メソッドを呼び出して影を作成します。 エフェクトがアタッチされているコントロールに Control.Layer
プロパティがない場合に備えて、この機能が try
/catch
ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached
メソッドによる実装は提供されません。
ユニバーサル Windows プラットフォーム プロジェクト
ユニバーサル Windows プラットフォーム (UWP) プロジェクト用の LabelShadowEffect
の実装を次のコード例に示します。
[assembly: ResolutionGroupName ("Xamarin")]
[assembly: ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.UWP
{
public class LabelShadowEffect : PlatformEffect
{
bool shadowAdded = false;
protected override void OnAttached ()
{
try {
if (!shadowAdded) {
var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
if (effect != null) {
var textBlock = Control as Windows.UI.Xaml.Controls.TextBlock;
var shadowLabel = new Label ();
shadowLabel.Text = textBlock.Text;
shadowLabel.FontAttributes = FontAttributes.Bold;
shadowLabel.HorizontalOptions = LayoutOptions.Center;
shadowLabel.VerticalOptions = LayoutOptions.CenterAndExpand;
shadowLabel.TextColor = effect.Color;
shadowLabel.TranslationX = effect.DistanceX;
shadowLabel.TranslationY = effect.DistanceY;
((Grid)Element.Parent).Children.Insert (0, shadowLabel);
shadowAdded = true;
}
}
} catch (Exception ex) {
Debug.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached ()
{
}
}
}
ユニバーサル Windows プラットフォームは影エフェクトを提供しないため、両方のプラットフォーム上の LabelShadowEffect
実装は 2 番目のオフセット Label
をプライマリ Label
の背後に追加することで、その 1 つをシミュレートします。 OnAttached
メソッドによって ShadowEffect
インスタンスが取得され、新しい Label
を作成され、Label
にいくつかのレイアウト プロパティが設定されます。 次に、Label
の色と場所を制御する TextColor
、TranslationX
、TranslationY
プロパティを設定することで影が作成されます。 これにより、shadowLabel
のプライマリ Label
の背後にオフセットが挿入されます。 エフェクトがアタッチされているコントロールに Control.Layer
プロパティがない場合に備えて、この機能が try
/catch
ブロック内にラップされます。 クリーンアップする必要がないので、OnDetached
メソッドによる実装は提供されません。
まとめ
この記事では、CLR プロパティを使用してエフェクトにパラメーターを渡す方法について説明しました。 CLR プロパティは、実行時のプロパティの変更に応答しないエフェクトのパラメーターの定義に使用できます。