Поделиться через


Передача параметров эффекта в качестве свойств среды CLR

Свойства общеязыковой среды выполнения (CLR) можно использовать для определения параметров эффекта, не реагирующих на изменения свойств во время выполнения. В этой статье демонстрируется использование свойств среды CLR для передачи параметров эффекту.

Процесс создания параметров эффектов, которые не реагируют на изменения свойств во время выполнения, состоит из указанных далее этапов.

  1. Создайте класс public, являющийся подклассом класса RoutingEffect. Класс RoutingEffect представляет независимый от платформы эффект, являющийся оболочкой для внутреннего эффекта, который обычно специфичен для платформы.
  2. Создайте конструктор, вызывающий конструктор базового класса с передачей объединения имени группы разрешения и уникального идентификатора, который был указан для каждого зависящего от платформы класса эффекта.
  3. Добавьте в класс свойства для каждого параметра, передаваемого эффекту.

Затем параметры можно передать эффекту, указав значение каждого свойства при создании экземпляра эффекта.

В примере приложения показан эффект ShadowEffect, который добавляет тень к тексту, отображаемому элементом управления Label. На следующей схеме показаны обязанности каждого проекта в примере приложения, а также связи между ними:

Задачи проекта для эффекта тени

Элемент управления Label в HomePage настраивается с помощью класса LabelShadowEffect в каждом проекте для конкретной платформы. Параметры передаются каждому эффекту LabelShadowEffect через свойства в классе ShadowEffect. Каждый класс LabelShadowEffect является производным от класса PlatformEffect для каждой платформы. В результате тень добавляется к тексту, отображаемому элементом управления Label, как показано на следующих снимках экрана.

Эффект тени на каждой платформе

Создание параметров эффекта

Необходимо создать класс public, являющийся подклассом класса RoutingEffect, для представления параметров эффекта, как показано в следующем примере кода:

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 в коллекцию Effects элемента управления добавляется новый экземпляр MyCompany.LabelShadowEffect.

Использование эффекта

В следующем примере кода XAML показан элемент управления Label, к которому присоединяется ShadowEffect:

<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>

В следующем примере кода показан эквивалентный элемент управления Label на языке C#.

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

В следующем примере кода показана реализация класса LabelShadowEffect для проекта на платформе iOS:

[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

В следующем примере кода показана реализация класса LabelShadowEffect для проекта на платформе Android:

[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

В следующем коде показана реализация класса LabelShadowEffect для проекта на универсальной платформе Windows (UWP):

[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 ()
        {
        }
    }
}

На платформе UWP эффект тени отсутствует, поэтому реализация LabelShadowEffect на обеих платформах имитирует его, добавляя второй класс смещения Label за основной экземпляр Label. Метод OnAttached получает экземпляр ShadowEffect, создает элемент управления Label и задает для Label определенные свойства макета. Затем он создает тень, задавая свойства TextColor, TranslationX и TranslationY для управления цветом и расположением Label. shadowLabel является смещением, вставленным за основной экземпляр Label. Ели у элемента управления, к которому присоединен эффект, отсутствуют свойства Control.Layer, указанная выше функциональность заключается в блок try/catch. Поскольку очистка не требуется, метод OnDetached не предоставляет реализацию.

Итоги

В этой статье было продемонстрировано использование свойств среды CLR для передачи параметров эффекту. Свойства среды CLR можно использовать для определения параметров эффекта, не реагирующих на изменения свойств во время выполнения.