Passando parâmetros de efeito como propriedades de Common Language Runtime
Propriedades de CLR (Common Language Runtime) podem ser usadas para definir parâmetros de efeito que não respondem a alterações de propriedade de tempo de execução. Este artigo demonstra como usar propriedades de CLR para passar parâmetros para um efeito.
O processo para criar parâmetros de efeito que não respondem a alterações de propriedade de runtime é o seguinte:
- Criar uma
public
que cria subclasses da classeRoutingEffect
. A classeRoutingEffect
representa um efeito independente de plataforma que encapsula um efeito interno, que é geralmente é específico da plataforma. - Crie um construtor que chama o construtor da classe base, passando uma concatenação do nome do grupo de resolução e a ID exclusiva que foi especificada em cada classe de efeito específica da plataforma.
- Adicione propriedades à classe para cada parâmetro a ser passado para o efeito.
Em seguida, os parâmetros podem ser passados para o efeito especificando valores para cada propriedade ao instanciar o efeito.
O aplicativo de exemplo demonstra um ShadowEffect
que adiciona uma sombra ao texto exibido por um controle Label
. O seguinte diagrama ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações entre elas:
Um controle Label
no HomePage
é personalizado pelo LabelShadowEffect
em cada projeto específico da plataforma. Os parâmetros são passados para cada LabelShadowEffect
por meio das propriedades na classe ShadowEffect
. Cada classe LabelShadowEffect
é derivada da classe PlatformEffect
de cada plataforma. Isso faz com que uma sombra seja adicionada ao texto exibido pelo controle Label
, conforme mostrado nas capturas de tela seguir:
Criando parâmetros de efeito
Uma classe public
que cria subclasses da classe RoutingEffect
deve ser criada para representar os parâmetros em vigor, conforme demonstrado no exemplo de código a seguir:
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")
{
}
}
O ShadowEffect
contém quatro propriedades que representam os parâmetros a serem passados para cada LabelShadowEffect
específico da plataforma. O construtor de classe chama o construtor da classe base, passando um parâmetro composto por uma concatenação do nome do grupo de resolução e pela ID exclusiva que foi especificada em cada classe de efeito específica da plataforma. Portanto, uma nova instância de MyCompany.LabelShadowEffect
será adicionada à coleção Effects
do controle quando um ShadowEffect
for instanciado.
Consumindo o efeito
O exemplo de código XAML abaixo mostra um controle Label
ao qual o ShadowEffect
está anexado:
<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>
O Label
equivalente em C# é mostrado no exemplo de código a seguir:
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
});
Nos dois exemplos de código, uma instância da classe ShadowEffect
é criada, com valores especificados para cada propriedade, antes de ser adicionada à coleção Effects
do controle. Observe que a propriedade ShadowEffect.Color
usa valores de cor específicos da plataforma. Para obter mais informações, confira Classe do dispositivo.
Criando o efeito em cada plataforma
As seções a seguir abordam a implementação da classe LabelShadowEffect
específica da plataforma.
Projeto do iOS
O exemplo de código a seguir mostra a implementação de LabelShadowEffect
para o projeto do 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 ()
{
}
}
}
O método OnAttached
recupera a instância de ShadowEffect
e define propriedades de Control.Layer
como os valores de propriedade especificados para criar a sombra. Essa funcionalidade é encapsulada em um bloco try
/catch
caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer
. Nenhuma implementação é fornecida pelo método OnDetached
porque nenhuma limpeza é necessária.
Projeto do Android
O exemplo de código a seguir mostra a implementação de LabelShadowEffect
para o projeto do 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 ()
{
}
}
}
O método OnAttached
recupera a instância de ShadowEffect
e chama o método TextView.SetShadowLayer
para criar uma sombra usando os valores de propriedade especificados. Essa funcionalidade é encapsulada em um bloco try
/catch
caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer
. Nenhuma implementação é fornecida pelo método OnDetached
porque nenhuma limpeza é necessária.
Projeto da Plataforma Universal do Windows
O exemplo de código a seguir mostra a implementação de LabelShadowEffect
para o projeto da UWP (Plataforma Universal do Windows):
[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 ()
{
}
}
}
A Plataforma Universal do Windows não fornece um efeito de sombra, de forma que a implementação de LabelShadowEffect
nas duas plataformas simula o efeito adicionando um segundo deslocamento Label
atrás do Label
principal. O método OnAttached
recupera a instância de ShadowEffect
, cria o novo Label
e define algumas propriedades de layout no Label
. Depois, ele cria a sombra definindo as propriedades TextColor
, TranslationX
e TranslationY
para controlar a cor e a localização do Label
. Em seguida, o shadowLabel
é inserido deslocado atrás do Label
principal. Essa funcionalidade é encapsulada em um bloco try
/catch
caso o controle a que o efeito está anexado não tenha as propriedades de Control.Layer
. Nenhuma implementação é fornecida pelo método OnDetached
porque nenhuma limpeza é necessária.
Resumo
Este artigo demonstrou como usar propriedades de CLR para passar parâmetros para um efeito. Propriedades de CLR podem ser usadas para definir parâmetros de efeito que não respondem a alterações de propriedade de runtime.