Xamarin.Forms Opakovaně použitelný RoundEffect
Důležité
Už není nutné použít RoundEffect
k vykreslení ovládacího prvku jako kruh. Nejnovějším doporučeným přístupem je vystřižovat ovládací prvek pomocí EllipseGeometry
ovládacího prvku . Další informace najdete v tématu Klipování s geometrií.
RoundEffect zjednodušuje vykreslování jakéhokoli ovládacího prvku, který je odvozený z VisualElement
kruhu. Tento efekt lze použít k vytváření cyklických obrázků, tlačítek a dalších ovládacích prvků:
Vytvoření sdílené třídy RoutingEffect
Třída efektu musí být vytvořena ve sdíleném projektu, aby se vytvořil efekt pro různé platformy. Ukázková aplikace vytvoří prázdnou RoundEffect
RoutingEffect
třídu, která je odvozena od třídy:
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
Tato třída umožňuje sdílenému projektu přeložit odkazy na účinek v kódu nebo XAML, ale neposkytuje žádné funkce. Účinek musí mít implementace pro každou platformu.
Implementace efektu Androidu
Projekt platformy Android definuje RoundEffect
třídu, která je odvozena od PlatformEffect
. Tato třída je označena assembly
atributy, které umožňují Xamarin.Forms přeložit třídu efektu:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
Platforma Android používá koncept definice OutlineProvider
okrajů ovládacího prvku. Ukázkový projekt obsahuje CornerRadiusProvider
třídu, která je odvozena z ViewOutlineProvider
třídy:
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);
}
}
Tato třída používá Width
a Height
vlastnosti Xamarin.FormsElement
instance k výpočtu poloměru, který je polovinou nejkratší dimenze.
Jakmile je zprostředkovatel osnovy definován, RoundEffect
třída ji může využívat k implementaci efektu:
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;
}
}
}
Metoda OnAttached
je volána, když je efekt připojen k elementu. Existující OutlineProvider
objekt je uložen, takže jej lze obnovit při odpojení efektu. Nová instance se CornerRadiusOutlineProvider
používá jako OutlineProvider
a ClipToOutline
je nastavena na hodnotu true pro oříznutí přetečení prvků na ohraničení obrysu.
Metoda OnDetatched
je volána při odebrání efektu z elementu a obnoví původní OutlineProvider
hodnotu.
Poznámka:
V závislosti na typu Control
prvku může nebo nemusí být vlastnost null. Control
Pokud vlastnost není null, lze zaoblené rohy použít přímo na ovládací prvek. Pokud však má hodnotu null, musí být u objektu Container
použity zaoblené rohy. Pole effectTarget
umožňuje použití efektu u příslušného objektu.
Implementace efektu iOS
Projekt platformy iOS definuje RoundEffect
třídu, která je odvozena od PlatformEffect
. Tato třída je označena assembly
atributy, které umožňují Xamarin.Forms přeložit třídu efektu:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
V iOSu Layer
mají ovládací prvky vlastnost, která má CornerRadius
vlastnost. Implementace RoundEffect
třídy v iOSu vypočítá odpovídající poloměr rohu a aktualizuje vlastnost vrstvy CornerRadius
:
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;
}
}
Metoda CalculateRadius
vypočítá poloměr na základě minimální dimenze Xamarin.FormsElement
. Metoda OnAttached
se volá, když je efekt připojen k ovládacímu prvku a aktualizuje vlastnost vrstvy CornerRadius
. ClipToBounds
Nastaví vlastnost tak, aby true
přetečení prvků byly oříznuty na ohraničení ovládacího prvku. Metoda OnDetatched
je volána při odebrání efektu z ovládacího prvku a obrátí tyto změny, obnovení původní rohový poloměr.
Poznámka:
V závislosti na typu Control
prvku může nebo nemusí být vlastnost null. Control
Pokud vlastnost není null, lze zaoblené rohy použít přímo na ovládací prvek. Pokud však má hodnotu null, musí být u objektu Container
použity zaoblené rohy. Pole effectTarget
umožňuje použití efektu u příslušného objektu.
Využití efektu
Jakmile se efekt implementuje na různých platformách, můžou ho Xamarin.Forms využívat ovládací prvky. Běžnou aplikací objektu RoundEffect
Image
je kruhový objekt. Následující XAML ukazuje efekt použitý u Image
instance:
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
Účinek lze použít také v kódu:
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
Třídu RoundEffect
lze použít na jakýkoli ovládací prvek, který je odvozen z VisualElement
.
Poznámka:
Aby bylo možné vypočítat správný poloměr, musí mít ovládací prvek, na který se použije explicitní nastavení velikosti. Proto by měly být definovány HeightRequest
vlastnosti a WidthRequest
vlastnosti. Pokud se ovlivněný ovládací prvek zobrazí v objektu StackLayout
, HorizontalOptions
jeho vlastnost by neměla používat jednu z hodnot Rozbalit , například LayoutOptions.CenterAndExpand
nebo nebude mít přesné rozměry.