平台特定内容
平台特定的功能让你可以使用仅在特定平台上提供的功能,而无需实现自定义呈现器或效果。
通过 XAML 或 Fluent 代码 API 使用特定于平台的过程如下所示:
- 为
Xamarin.Forms.PlatformConfiguration
命名空间添加xmlns
声明或using
指令。 - 为包含特定于平台的功能的命名空间添加
xmlns
声明或using
指令:- 在 iOS 上,这是
Xamarin.Forms.PlatformConfiguration.iOSSpecific
命名空间。 - 在 Android 上,这是
Xamarin.Forms.PlatformConfiguration.AndroidSpecific
命名空间。 对于 Android AppCompat,这是Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat
命名空间。 - 在通用 Windows 平台上,这是
Xamarin.Forms.PlatformConfiguration.WindowsSpecific
命名空间。
- 在 iOS 上,这是
- 使用
On<T>
Fluent API 通过 XAML 或代码应用特定于平台的内容。T
的值可以是Xamarin.Forms.PlatformConfiguration
命名空间中的iOS
、Android
或Windows
类型。
注意
请注意,尝试在特定于平台的内容不可用的平台上使用它将不会造成错误。 相反,代码将执行,而不会应用特定于平台的内容。
通过 On<T>
Fluent 代码 API 使用的特定于平台的内容会返回 IPlatformElementConfiguration
对象。 这样,就可以使用方法级联在同一对象上调用多个特定于平台的内容。
有关 Xamarin.Forms 提供的特定于平台的内容的详细信息,请参阅 iOS 平台特定、Android 平台特定和 Windows 平台特定。
创建平台特定内容
供应商可以使用效果创建自己的平台特定内容。 效果可提供特定功能,功能通过特定于平台的内容公开。 结果是一种效果,可通过 XAML 和 Fluent 代码 API 更轻松地使用。
创建特定于平台的内容的过程如下所示:
- 将特定功能实现为效果。 有关详细信息,请参阅创建效果。
- 创建一个平台特定的类,该类将公开效果。 有关详细信息,请参阅创建特定于平台的类。
- 在特定于平台的类中,实现附加属性,以允许通过 XAML 使用特定于平台的内容。 有关详细信息,请参阅添加附加属性。
- 在特定于平台的类中,实现扩展方法,以允许通过 Fluent 代码 API 使用特定于平台的内容。 有关详细信息,请参阅添加扩展方法。
- 修改效果实现,以便仅在与效果相同的平台上调用特定于平台的内容时应用效果。 有关详细信息,请参阅创建效果。
将效果公开为特定于平台的内容的结果是,可以通过 XAML 和 Fluent 代码 API 更轻松地使用效果。
注意
预计供应商将使用此技术创建自己的平台特定内容,以便用户轻松使用它们。 虽然用户可以选择创建自己的平台特定内容,但应指出,它需要比创建和使用效果更多的代码。
示例应用程序展示了特定于平台的 Shadow
,它将向 Label
控件显示的文本添加阴影:
示例应用程序将在每个平台上实现特定于平台的 Shadow
,以便于读者理解。 但是,除了每个特定于平台的效果实现之外,阴影类的实现对于每个平台来说基本上都是相同的。 因此,本指南重点介绍阴影类的实现以及单个平台上的关联效果。
有关效果的详细信息,请参阅使用效果自定义控件。
创建特定于平台的类
特定于平台的类创建为 public static
类:
namespace MyCompany.Forms.PlatformConfiguration.iOS
{
public static Shadow
{
...
}
}
以下部分讨论 Shadow
平台特定内容和关联的效果的实现。
添加附加属性
必须将附加属性添加到 Shadow
平台特定内容,以允许通过 XAML 使用:
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
集合,在控件中添加或移除效果。
注意
请注意,效果是通过指定一个值来解析的,该值是在效果实现上指定的解析组名称和唯一标识符的串联。 有关详细信息,请参阅创建效果。
有关附加属性的详细信息,请参阅附加属性。
添加扩展方法
必须将扩展方法添加到 Shadow
平台特定内容,以允许通过 Fluent 代码 API 使用:
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.LabelShadowEffect
添加到 Label
,以及将其移除。 以下代码示例展示了 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);
}
}
}
}
UpdateShadow
方法会设置 Control.Layer
属性以创建阴影,前提是 IsShadowed
附加属性设置为 true
,且已在实现效果的同一平台上调用了 Shadow
特定于平台的内容。 此检查通过 OnThisPlatform
方法执行。
如果 Shadow.IsShadowed
附加属性值在运行时发生更改,则效果需要通过移除阴影来响应。 因此,OnElementPropertyChanged
方法的替代版本用于通过调用 UpdateShadow
方法来响应可绑定属性更改。
有关创建效果的详细信息,请参阅创建效果以及传递效果参数作为附加属性。
使用特定于平台的内容
通过将 Shadow.IsShadowed
附加属性设置为 boolean
值,在 XAML 中使用 Shadow
特定于平台的内容:
<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);