將效果參數當作 Common Language Runtime 屬性傳遞
Common Language Runtime (CLR) 屬性可用來定義不會回應執行階段屬性變更的效果參數。 本文示範如何使用 CLR 屬性將參數傳遞至效果。
建立不會回應執行階段屬性變更之效果參數的程序如下:
- 建立將
RoutingEffect
類別子類別化的public
類別。RoutingEffect
類別代表包裝通常是平台特定之內部效果的平台獨立效果。 - 建立呼叫基底類別建構函式的建構函式,並傳入解析群組名稱串連,以及每個平台特定效果類別所指定的唯一識別碼。
- 針對每個要傳遞至效果的參數,將屬性新增至其類別。
然後在具現化效果時,透過指定每個屬性的值來將參數傳遞至效果。
範例應用程式所示範的 ShadowEffect
會將陰影新增至 Label
控制項所顯示的文字。 下圖說明應用程式範例中每個專案的責任,以及這些專案之間的關聯性:
HomePage
上的 Label
控制項是由每個平台特定專案中的 LabelShadowEffect
所自訂。 透過 ShadowEffect
類別中的屬性,將參數傳遞至每個 LabelShadowEffect
。 每個 LabelShadowEffect
類別都衍生自每個平台的 PlatformEffect
類別。 這會導致將陰影新增至 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
的參數。 類別建構函式會呼叫基底類別建構函式,並傳入由解析群組名稱串連組成的參數,以及每個平台特定效果類別所指定的唯一識別碼。 因此,具現化 ShadowEffect
時,會將 MyCompany.LabelShadowEffect
的新執行個體新增至控制項的 Effects
集合。
使用效果
下列 XAML 程式碼範例示範 ShadowEffect
所附加的 Label
控制項:
<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
屬性使用平台特定的色彩值。 如需詳細資訊,請參閱裝置類別。
在每個平台上建立效果
下列各節會討論 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
屬性設定為指定的屬性值以建立陰影。 這項功能會包裝在 try
/catch
區塊中,以免效果附加至的控制項沒有 Control.Layer
屬性。 因為沒有必要的清除,所以 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
方法以使用指定的屬性值來建立陰影。 這項功能會包裝在 try
/catch
區塊中,以免效果附加至的控制項沒有 Control.Layer
屬性。 因為沒有必要的清除,所以 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
實作會透過在主要 Label
後方新增第二個偏移的 Label
來模擬此效果。 OnAttached
方法會擷取 ShadowEffect
執行個體、建立新的 Label
,並在 Label
上設定一些配置屬性。 然後設定 TextColor
、TranslationX
和 TranslationY
屬性來控制 Label
的色彩和位置,藉此建立陰影。 shadowLabel
會接著偏移插入在主要 Label
的後方。 這項功能會包裝在 try
/catch
區塊中,以免效果附加至的控制項沒有 Control.Layer
屬性。 因為沒有必要的清除,所以 OnDetached
方法不提供實作。
摘要
本文示範了如何使用 CLR 屬性將參數傳遞至效果。 CLR 屬性可用來定義不會回應執行階段屬性變更的效果參數。