将效果参数作为公共语言运行时属性传递
公共语言运行时 (CLR) 属性可用于定义不响应运行时属性更改的效果参数。 本文演示如何使用 CLR 属性将参数传递给效果。
创建不响应运行时属性更改的效果参数的过程如下:
- 创建一个
public
类,它将RoutingEffect
类作为子类。RoutingEffect
类表示独立于平台的效果,该效果包装通常特定于平台的内部效果。 - 创建一个调用基类构造函数的构造函数,传递解析组名称以及每个特定于平台的效果类上指定的唯一 ID 的串联。
- 为要传递给效果的每个参数向类添加属性。
在实例化效果时,为每个属性指定值可将参数传递给效果。
示例应用程序展示了向 Label
控件显示的文本添加阴影的 ShadowEffect
。 下图说明了示例应用程序中每个项目的职责,以及它们之间的关系:
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
的参数。 类构造函数调用基类构造函数,传入由解析组名称以及每个特定于平台的效果类上指定的唯一 ID 的串联组成的参数。 因此,在实例化 ShadowEffect
时,将向控件的 Effects
集合添加 MyCompany.LabelShadowEffect
的新实例。
使用效果
下面的 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
属性使用特定于平台的颜色值。 有关详细信息,请参阅 Device 类。
在各平台上创建效果
以下各部分讨论特定于平台的 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
实现通过在主 Label
后面添加第二个偏移 Label
来进行模拟。 OnAttached
方法检索 ShadowEffect
实例,创建新的 Label
,并在 Label
上设置一些布局属性。 然后通过设置 TextColor
、TranslationX
和 TranslationY
属性来控制 Label
的颜色和位置,从而创建阴影。 shadowLabel
随后插入主 Label
后面并偏移。 效果所附加到的控件没有 Control.Layer
属性时,此功能包装在 try
/catch
块中。 OnDetached
方法不提供任何实现,因为不需要进行清理。
总结
本文演示如何使用 CLR 属性将参数传递给效果。 CLR 属性可用于定义不响应运行时属性更改的效果参数。