Aracılığıyla paylaş


Xamarin.Forms Yeniden Kullanılabilir RoundEffect

Önemli

Artık denetimi daire olarak işlemek için kullanmak RoundEffect gerekli değildir. Önerilen en son yaklaşım, kullanarak EllipseGeometrydenetimi kırpmaktır. Daha fazla bilgi için bkz . Geometri ile kırpma.

RoundEffect, 'den bir daire olarak türetilen tüm denetimlerin işlenmesini VisualElement basitleştirir. Bu efekt dairesel görüntüler, düğmeler ve diğer denetimler oluşturmak için kullanılabilir:

iOS ve Android'de RoundEffect ekran görüntüleri

Paylaşılan routingeffect oluşturma

Platformlar arası etki oluşturmak için paylaşılan projede bir efekt sınıfı oluşturulmalıdır. Örnek uygulama, sınıfından türetilen RoutingEffect boş RoundEffect bir sınıf oluşturur:

public class RoundEffect : RoutingEffect
{
    public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
    {
    }
}

Bu sınıf, paylaşılan projenin kod veya XAML'deki efekt başvurularını çözümlemesine izin verir, ancak herhangi bir işlev sağlamaz. Etkinin her platform için uygulamaları olmalıdır.

Android efektini uygulama

Android platform projesi, öğesinden PlatformEffecttüretilen bir RoundEffect sınıf tanımlar. Bu sınıf, efekt sınıfını çözümlemeye izin veren Xamarin.Forms özniteliklerle assembly etiketlendi:

[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
    public class RoundEffect : PlatformEffect
    {
        // ...
    }
}

Android platformu, denetimin OutlineProvider kenarlarını tanımlamak için bir kavramını kullanır. Örnek proje, sınıfından türetilen ViewOutlineProvider bir CornerRadiusProvider sınıf içerir:

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);
    }
}

Bu sınıf, en kısa boyutun yarısı olan bir yarıçapı hesaplamak için örneğin ve Height özelliklerini kullanırWidth.Xamarin.FormsElement

Ana hat sağlayıcısı tanımlandıktan RoundEffect sonra sınıfı efekti uygulamak için bunu kullanabilir:

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;
        }
    }
}

OnAttached yöntemi, efekt bir öğeye eklendiğinde çağrılır. Mevcut OutlineProvider nesne kaydedilir, böylece etki ayrılınca geri yüklenebilir. öğesinin CornerRadiusOutlineProvider yeni bir örneği kullanılır veClipToOutline, taşan öğeleri ana hat kenarlıklarına kırpmak için true olarak OutlineProvider ayarlanır.

yöntemi OnDetatched , efekt bir öğeden kaldırıldığında ve özgün OutlineProvider değeri geri yüklediğinde çağrılır.

Not

Öğe türüne bağlı olarak özelliği Control null olabilir veya olmayabilir. Control Özellik null değilse, yuvarlatılmış köşeler doğrudan denetime uygulanabilir. Ancak null ise, yuvarlatılmış köşeler nesneye Container uygulanmalıdır. alanı, effectTarget efektin uygun nesneye uygulanmasını sağlar.

iOS efektini uygulama

iOS platform projesi, öğesinden PlatformEffecttüretilen bir RoundEffect sınıf tanımlar. Bu sınıf, efekt sınıfını çözümlemeye izin veren Xamarin.Forms özniteliklerle assembly etiketlendi:

[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
    public class RoundEffect : PlatformEffect
    {
        // ...
    }

iOS'ta denetimlerin özelliği Layer olan bir CornerRadius özelliği vardır. iOS'ta RoundEffect sınıf uygulaması uygun köşe yarıçapını hesaplar ve katmanın CornerRadius özelliğini güncelleştirir:

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;
    }
}

yöntemi, CalculateRadius en düşük boyutuna Xamarin.FormsElementgöre bir yarıçap hesaplar. OnAttached yöntemi, efekt bir denetime eklendiğinde çağrılır ve katmanın CornerRadius özelliğini güncelleştirir. özelliğinitrue, taşan öğelerin denetimin kenarlıklarına kırpılması için olarak ayarlarClipToBounds. Yöntem OnDetatched , etki bir denetimden kaldırıldığında çağrılır ve bu değişiklikleri tersine çevirerek özgün köşe yarıçapını geri yükler.

Not

Öğe türüne bağlı olarak özelliği Control null olabilir veya olmayabilir. Control Özellik null değilse, yuvarlatılmış köşeler doğrudan denetime uygulanabilir. Ancak null ise, yuvarlatılmış köşeler nesneye Container uygulanmalıdır. alanı, effectTarget efektin uygun nesneye uygulanmasını sağlar.

Efekti kullanma

Etki platformlar arasında uygulandıktan sonra denetimler tarafından Xamarin.Forms kullanılabilir. 'nin RoundEffect yaygın bir uygulaması, bir Image nesneyi döngüsel hale getirmektir. Aşağıdaki XAML bir örneğe uygulanan Image efekti gösterir:

<Image Source=outdoors"
       HeightRequest="100"
       WidthRequest="100">
    <Image.Effects>
        <local:RoundEffect />
    </Image.Effects>
</Image>

Efekt koda da uygulanabilir:

var image = new Image
{
    Source = ImageSource.FromFile("outdoors"),
    HeightRequest = 100,
    WidthRequest = 100
};
image.Effects.Add(new RoundEffect());

sınıfı, RoundEffect öğesinden VisualElementtüretilen herhangi bir denetime uygulanabilir.

Not

Efektin doğru yarıçapı hesaplaması için uygulandığı denetimin açık boyutlandırmaya sahip olması gerekir. Bu nedenle ve HeightRequestWidthRequest özellikleri tanımlanmalıdır. Etkilenen denetim içinde StackLayoutgörünüyorsa, özelliği HorizontalOptions gibi LayoutOptions.CenterAndExpand Genişletme değerlerinden birini kullanmamalıdır, aksi takdirde doğru boyutlara sahip olmaz.