共用方式為


平台專用

平臺特定專案可讓您取用只能在特定平臺上使用的功能,而不需要實作自定義轉譯器或效果。

透過 XAML 或 Fluent 程式代碼 API 取用平臺專屬的程式如下:

  1. xmlns為命名空間新增宣告或using指示詞Xamarin.Forms.PlatformConfiguration
  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. 使用 Fluent API 從 XAML 或從程式碼套用 On<T> 平臺特定的 。 的值T可以是命名空間中的 iOSXamarin.Forms.PlatformConfigurationAndroidWindows 型別。

注意

請注意,嘗試在無法使用平臺的平臺上取用平臺特定,將不會產生錯誤。 相反地,程式代碼會在不套用平臺特定的情況下執行。

透過 Fluent 程式代碼 API 傳回IPlatformElementConfiguration物件取用On<T>的平臺特定專案。 這可讓多個平臺特定專案在具有方法串聯的相同物件上叫用。

如需 所提供Xamarin.Forms平臺特定項目的詳細資訊,請參閱 iOS 平臺特定、Android 平臺特定和 Windows 平臺特定。

建立平臺特定專案

廠商可以使用 Effects 建立自己的平臺特定專案。 效果會提供特定功能,然後透過平臺特定公開。 結果是一種效果,可透過 XAML 和 Fluent 程式代碼 API 更輕鬆地取用。

建立平台專屬的程式如下:

  1. 實作特定功能做為效果。 如需詳細資訊,請參閱 建立效果
  2. 建立將公開 Effect 的平臺特定類別。 如需詳細資訊,請參閱 建立平臺特定類別
  3. 在平臺特定類別中,實作附加屬性,以允許透過 XAML 取用平臺特定的屬性。 如需詳細資訊,請參閱 新增附加屬性
  4. 在平臺特定類別中,實作擴充方法,以允許透過 Fluent 程式代碼 API 取用平台專屬。 如需詳細資訊,請參閱 新增擴充方法
  5. 修改 Effect 實作,只有在與 Effect 相同的平臺上叫用平臺特定時,才會套用 Effect。 如需詳細資訊,請參閱 建立效果

將 Effect 公開為平臺特有的結果,就是效果可以透過 XAML 和 Fluent 程式代碼 API 更輕鬆地取用。

注意

其設想廠商會使用這項技術來建立自己的平臺特定專案,以方便用戶取用。 雖然使用者可以選擇建立自己的平臺特定專案,但應該注意,它需要比建立和使用效果更多的程序代碼。

範例應用程式示範平臺 Shadow 特定,可將陰影新增至控件所 Label 顯示的文字:

陰影平臺特定

範例應用程式會在每個平臺上實作 Shadow 平台專屬,以方便瞭解。 不過,除了每個平臺特定的 Effect 實作之外,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附加屬性是用來將 Effect 新增MyCompany.LabelShadowEffect至 ,並將它從 附加類別的控件Shadow中移除。 此附加屬性會註冊 OnIsShadowedPropertyChanged 方法;當屬性的值變更時,就會執行此方法。 接著,這個方法會呼叫 AttachEffectDetachEffect 方法,根據附加屬性的值 IsShadowed 來新增或移除效果。 修改控件的 Effects 集合,即會將 Effect 新增至控件或從控件中移除。

注意

請注意,效果的解析方式是指定解析組名串連的值,以及效果實作上指定的唯一標識符。 如需詳細資訊,請參閱 建立效果

如需附加屬性的詳細資訊,請參閱附加屬性

新增擴充方法

擴充方法必須新增至 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;
        }
        ...
    }
}

IsShadowedSetIsShadowed 擴充方法會分別叫用附加屬性的 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);
            }
        }
    }
}

方法會將 UpdateShadow 屬性設定 Control.Layer 為建立陰影,前提是 IsShadowed 附加屬性設定為 true,而且前提是 Shadow 已在實作 Effect 的相同平臺上叫用平臺特定。 這個檢查是使用 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);