Xamarin.Forms RoundEffect riutilizzabile
Importante
Non è più necessario usare un RoundEffect
oggetto per eseguire il rendering di un controllo come cerchio. L'approccio consigliato più recente consiste nel ritagliare il controllo usando un oggetto EllipseGeometry
. Per altre informazioni, vedere Ritaglia con una geometria.
RoundEffect semplifica il rendering di qualsiasi controllo che deriva da VisualElement
come cerchio. Questo effetto può essere usato per creare immagini circolari, pulsanti e altri controlli:
Creare un routing condivisoEffect
Per creare un effetto multipiattaforma, è necessario creare una classe di effetto nel progetto condiviso. L'applicazione di esempio crea una classe vuota RoundEffect
che deriva dalla RoutingEffect
classe :
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
Questa classe consente al progetto condiviso di risolvere i riferimenti all'effetto nel codice o xaml, ma non fornisce alcuna funzionalità. L'effetto deve avere implementazioni per ogni piattaforma.
Implementare l'effetto Android
Il progetto di piattaforma Android definisce una RoundEffect
classe che deriva da PlatformEffect
. Questa classe è contrassegnata con assembly
attributi che consentono di Xamarin.Forms risolvere la classe dell'effetto:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
La piattaforma Android usa il concetto di un oggetto OutlineProvider
per definire i bordi di un controllo. Il progetto di esempio include una CornerRadiusProvider
classe che deriva dalla 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);
}
}
Questa classe utilizza le Width
proprietà e Height
dell'istanza Xamarin.FormsElement
per calcolare un raggio che è la metà della dimensione più breve.
Una volta definito un provider di struttura, la RoundEffect
classe può utilizzarla per implementare l'effetto:
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;
}
}
}
Il OnAttached
metodo viene chiamato quando l'effetto è associato a un elemento. L'oggetto esistente OutlineProvider
viene salvato in modo che possa essere ripristinato quando l'effetto viene scollegato. Una nuova istanza di CornerRadiusOutlineProvider
viene utilizzata come OutlineProvider
e ClipToOutline
viene impostata su true per ritagliare gli elementi di overflow ai bordi della struttura.
Il OnDetatched
metodo viene chiamato quando l'effetto viene rimosso da un elemento e ripristina il valore originale OutlineProvider
.
Nota
A seconda del tipo di elemento, la Control
proprietà può essere o meno Null. Se la Control
proprietà non è Null, gli angoli arrotondati possono essere applicati direttamente al controllo. Tuttavia, se è Null, gli angoli arrotondati devono essere applicati all'oggetto Container
. Il effectTarget
campo consente di applicare l'effetto all'oggetto appropriato.
Implementare l'effetto iOS
Il progetto di piattaforma iOS definisce una RoundEffect
classe che deriva da PlatformEffect
. Questa classe è contrassegnata con assembly
attributi che consentono di Xamarin.Forms risolvere la classe dell'effetto:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
In iOS i controlli hanno una Layer
proprietà , che ha una CornerRadius
proprietà . L'implementazione RoundEffect
della classe in iOS calcola il raggio dell'angolo appropriato e aggiorna la proprietà del CornerRadius
livello:
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;
}
}
Il CalculateRadius
metodo calcola un raggio in base alla dimensione minima dell'oggetto Xamarin.FormsElement
. Il OnAttached
metodo viene chiamato quando l'effetto viene associato a un controllo e aggiorna la proprietà del CornerRadius
livello. Imposta la ClipToBounds
proprietà su true
in modo che gli elementi di overflow vengano ritagliati ai bordi del controllo. Il OnDetatched
metodo viene chiamato quando l'effetto viene rimosso da un controllo e inverte queste modifiche, ripristinando il raggio dell'angolo originale.
Nota
A seconda del tipo di elemento, la Control
proprietà può essere o meno Null. Se la Control
proprietà non è Null, gli angoli arrotondati possono essere applicati direttamente al controllo. Tuttavia, se è Null, gli angoli arrotondati devono essere applicati all'oggetto Container
. Il effectTarget
campo consente di applicare l'effetto all'oggetto appropriato.
Utilizzare l'effetto
Una volta implementato l'effetto tra le piattaforme, può essere utilizzato dai Xamarin.Forms controlli. Un'applicazione comune di è la creazione di RoundEffect
un Image
oggetto circolare. Il codice XAML seguente mostra l'effetto applicato a un'istanza Image
:
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
L'effetto può essere applicato anche nel codice:
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
La RoundEffect
classe può essere applicata a qualsiasi controllo che deriva da VisualElement
.
Nota
Affinché l'effetto calcoli il raggio corretto, il controllo a cui viene applicato deve avere un ridimensionamento esplicito. Pertanto, è necessario definire le HeightRequest
proprietà e WidthRequest
. Se il controllo interessato viene visualizzato in un StackLayout
oggetto , la relativa HorizontalOptions
proprietà non deve utilizzare uno dei valori Expand , LayoutOptions.CenterAndExpand
ad esempio o non avrà dimensioni accurate.