Xamarin.Forms RoundEffect réutilisable
Important
Il n’est plus nécessaire d’utiliser un RoundEffect
contrôle pour afficher un contrôle en tant que cercle. La dernière approche recommandée consiste à découper le contrôle à l’aide d’un EllipseGeometry
. Pour plus d’informations, consultez Clip avec une géométrie.
RoundEffect simplifie le rendu de tout contrôle dérivé d’un VisualElement
cercle. Cet effet peut être utilisé pour créer des images circulaires, des boutons et d’autres contrôles :
Créer un RoutingEffect partagé
Une classe d’effet doit être créée dans le projet partagé pour créer un effet multiplateforme. L’exemple d’application crée une classe vide RoundEffect
qui dérive de la RoutingEffect
classe :
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
Cette classe permet au projet partagé de résoudre les références à l’effet dans le code ou xaml, mais ne fournit aucune fonctionnalité. L’effet doit avoir des implémentations pour chaque plateforme.
Implémenter l’effet Android
Le projet de plateforme Android définit une RoundEffect
classe qui dérive de PlatformEffect
. Cette classe est marquée avec assembly
des attributs qui permettent Xamarin.Forms de résoudre la classe d’effet :
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
La plateforme Android utilise le concept d’un OutlineProvider
pour définir les bords d’un contrôle. L’exemple de projet inclut une CornerRadiusProvider
classe qui dérive de la 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);
}
}
Cette classe utilise les propriétés et Height
les Width
propriétés de l’instance Xamarin.FormsElement
pour calculer un rayon qui correspond à la moitié de la dimension la plus courte.
Une fois qu’un fournisseur de plan est défini, la RoundEffect
classe peut l’utiliser pour implémenter l’effet :
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;
}
}
}
La OnAttached
méthode est appelée lorsque l’effet est attaché à un élément. L’objet existant OutlineProvider
est enregistré afin qu’il puisse être restauré lorsque l’effet est détaché. Une nouvelle instance du fichier CornerRadiusOutlineProvider
est utilisée comme OutlineProvider
valeur true pour ClipToOutline
découper les éléments débordants vers les bordures hiérarchiques.
La OnDetatched
méthode est appelée lorsque l’effet est supprimé d’un élément et restaure la valeur d’origine OutlineProvider
.
Remarque
Selon le type d’élément, la Control
propriété peut ou non être null. Si la Control
propriété n’est pas null, les angles arrondis peuvent être appliqués directement au contrôle. Toutefois, s’il s’agit de null, les angles arrondis doivent être appliqués à l’objet Container
. Le effectTarget
champ permet l’application de l’effet à l’objet approprié.
Implémenter l’effet iOS
Le projet de plateforme iOS définit une RoundEffect
classe qui dérive de PlatformEffect
. Cette classe est marquée avec assembly
des attributs qui permettent Xamarin.Forms de résoudre la classe d’effet :
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
Sur iOS, les contrôles ont une Layer
propriété, qui a une CornerRadius
propriété. L’implémentation RoundEffect
de classe sur iOS calcule le rayon d’angle approprié et met à jour la propriété de la CornerRadius
couche :
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;
}
}
La CalculateRadius
méthode calcule un rayon en fonction de la dimension minimale du Xamarin.FormsElement
. La OnAttached
méthode est appelée lorsque l’effet est attaché à un contrôle et met à jour la propriété de CornerRadius
la couche. Elle définit la ClipToBounds
propriété pour true
que les éléments débordants soient clippés aux bordures du contrôle. La OnDetatched
méthode est appelée lorsque l’effet est supprimé d’un contrôle et inverse ces modifications, en restaurant le rayon d’angle d’origine.
Remarque
Selon le type d’élément, la Control
propriété peut ou non être null. Si la Control
propriété n’est pas null, les angles arrondis peuvent être appliqués directement au contrôle. Toutefois, s’il s’agit de null, les angles arrondis doivent être appliqués à l’objet Container
. Le effectTarget
champ permet l’application de l’effet à l’objet approprié.
Consommer l’effet
Une fois l’effet implémenté sur plusieurs plateformes, il peut être consommé par Xamarin.Forms les contrôles. Une application courante de l’objet RoundEffect
fait circulaire un Image
objet. Le code XAML suivant montre l’effet appliqué à une Image
instance :
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
L’effet peut également être appliqué dans le code :
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
La RoundEffect
classe peut être appliquée à n’importe quel contrôle dérivé de VisualElement
.
Remarque
Pour que l’effet calcule le rayon correct, le contrôle auquel il est appliqué doit avoir un dimensionnement explicite. Par conséquent, les HeightRequest
propriétés doivent WidthRequest
être définies. Si le contrôle affecté apparaît dans un StackLayout
, sa HorizontalOptions
propriété ne doit pas utiliser l’une des valeurs Expand telles que LayoutOptions.CenterAndExpand
ou elle n’aura pas de dimensions précises.