Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Importante
Não é mais necessário usar um RoundEffect para renderizar um controle como um círculo. A última abordagem recomendada é cortar o controle usando um EllipseGeometryarquivo . Para obter mais informações, consulte Clipe com uma geometria.
O RoundEffect simplifica a renderização de qualquer controle derivado de VisualElement como um círculo. Esse efeito pode ser usado para criar imagens circulares, botões e outros controles:
Criar um RoutingEffect compartilhado
Uma classe de efeito deve ser criada no projeto compartilhado para criar um efeito entre plataformas. O aplicativo de exemplo cria uma classe vazia RoundEffect que deriva da RoutingEffect classe:
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
Essa classe permite que o projeto compartilhado resolva as referências ao efeito em código ou XAML, mas não fornece nenhuma funcionalidade. O efeito deve ter implementações para cada plataforma.
Implementar o efeito Android
O projeto da plataforma Android define uma RoundEffect classe que deriva de PlatformEffect. Essa classe é marcada com assembly atributos que permitem Xamarin.Forms resolver a classe de efeito:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
A plataforma Android usa o conceito de an OutlineProvider para definir as bordas de um controle. O projeto de exemplo inclui uma CornerRadiusProvider classe que deriva da ViewOutlineProvider classe:
class CornerRadiusOutlineProvider : ViewOutlineProvider
{
Element element;
public CornerRadiusOutlineProvider(Element formsElement)
{
element = formsElement;
}
public override void GetOutline(Android.Views.View view, Outline outline)
{
float scale = view.Resources.DisplayMetrics.Density;
double width = (double)element.GetValue(VisualElement.WidthProperty) * scale;
double height = (double)element.GetValue(VisualElement.HeightProperty) * scale;
float minDimension = (float)Math.Min(height, width);
float radius = minDimension / 2f;
Rect rect = new Rect(0, 0, (int)width, (int)height);
outline.SetRoundRect(rect, radius);
}
}
Essa classe usa as Width propriedades e Height da Xamarin.FormsElement instância para calcular um raio que é metade da dimensão mais curta.
Depois que um provedor de estrutura de tópicos é definido, a RoundEffect classe pode consumi-lo para implementar o efeito:
public class RoundEffect : PlatformEffect
{
ViewOutlineProvider originalProvider;
Android.Views.View effectTarget;
protected override void OnAttached()
{
try
{
effectTarget = Control ?? Container;
originalProvider = effectTarget.OutlineProvider;
effectTarget.OutlineProvider = new CornerRadiusOutlineProvider(Element);
effectTarget.ClipToOutline = true;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to set corner radius: {ex.Message}");
}
}
protected override void OnDetached()
{
if(effectTarget != null)
{
effectTarget.OutlineProvider = originalProvider;
effectTarget.ClipToOutline = false;
}
}
}
O OnAttached método é chamado quando o efeito é anexado a um elemento. O objeto existente OutlineProvider é salvo para que possa ser restaurado quando o efeito for desanexado. Uma nova instância do CornerRadiusOutlineProvider é usada como o OutlineProvider e ClipToOutline é definida como true para cortar elementos transbordantes para as bordas da estrutura de tópicos.
O OnDetatched método é chamado quando o efeito é removido de um elemento e restaura o valor original OutlineProvider .
Observação
Dependendo do tipo de elemento, a Control propriedade pode ou não ser nula. Se a Control propriedade não for nula, os cantos arredondados poderão ser aplicados diretamente ao controle. No entanto, se for nulo, os cantos arredondados devem ser aplicados ao Container objeto. O effectTarget campo permite que o efeito seja aplicado ao objeto apropriado.
Implementar o efeito iOS
O projeto da plataforma iOS define uma RoundEffect classe que deriva de PlatformEffect. Essa classe é marcada com assembly atributos que permitem Xamarin.Forms resolver a classe de efeito:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
No iOS, os controles têm uma Layer propriedade, que tem uma CornerRadius propriedade. A RoundEffect implementação de classe no iOS calcula o raio de canto apropriado e atualiza a propriedade da CornerRadius camada:
public class RoundEffect : PlatformEffect
{
nfloat originalRadius;
UIKit.UIView effectTarget;
protected override void OnAttached()
{
try
{
effectTarget = Control ?? Container;
originalRadius = effectTarget.Layer.CornerRadius;
effectTarget.ClipsToBounds = true;
effectTarget.Layer.CornerRadius = CalculateRadius();
}
catch (Exception ex)
{
Console.WriteLine($"Failed to set corner radius: {ex.Message}");
}
}
protected override void OnDetached()
{
if (effectTarget != null)
{
effectTarget.ClipsToBounds = false;
if (effectTarget.Layer != null)
{
effectTarget.Layer.CornerRadius = originalRadius;
}
}
}
float CalculateRadius()
{
double width = (double)Element.GetValue(VisualElement.WidthRequestProperty);
double height = (double)Element.GetValue(VisualElement.HeightRequestProperty);
float minDimension = (float)Math.Min(height, width);
float radius = minDimension / 2f;
return radius;
}
}
O CalculateRadius método calcula um raio com base na dimensão mínima do Xamarin.FormsElement. O OnAttached método é chamado quando o efeito é anexado a um controle e atualiza a propriedade da CornerRadius camada. Ele define a propriedade para true que os ClipToBounds elementos transbordantes sejam cortados nas bordas do controle. O OnDetatched método é chamado quando o efeito é removido de um controle e reverte essas alterações, restaurando o raio de canto original.
Observação
Dependendo do tipo de elemento, a Control propriedade pode ou não ser nula. Se a Control propriedade não for nula, os cantos arredondados poderão ser aplicados diretamente ao controle. No entanto, se for nulo, os cantos arredondados devem ser aplicados ao Container objeto. O effectTarget campo permite que o efeito seja aplicado ao objeto apropriado.
Consumir o efeito
Uma vez que o efeito é implementado em todas as plataformas, ele pode ser consumido por Xamarin.Forms controles. Uma aplicação comum do RoundEffect é tornar um Image objeto circular. O XAML a seguir mostra o efeito que está sendo aplicado a uma Image instância:
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
O efeito também pode ser aplicado no código:
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
A RoundEffect classe pode ser aplicada a qualquer controle derivado de VisualElement.
Observação
Para que o efeito calcule o raio correto, o controle ao qual ele é aplicado deve ter dimensionamento explícito. Portanto, as HeightRequest propriedades e WidthRequest devem ser definidas. Se o controle afetado aparecer em um StackLayout, sua HorizontalOptions propriedade não deve usar um dos valores Expand , como LayoutOptions.CenterAndExpand ou ele não terá dimensões precisas.
