Xamarin.Forms RoundEffect yang Dapat Digunakan Kembali
Penting
Tidak perlu lagi menggunakan RoundEffect
untuk merender kontrol sebagai lingkaran. Pendekatan terbaru yang direkomendasikan adalah mengklip kontrol menggunakan EllipseGeometry
. Untuk informasi selengkapnya, lihat Klip dengan Geometri.
RoundEffect menyederhanakan penyajian kontrol apa pun yang berasal dari VisualElement
sebagai lingkaran. Efek ini dapat digunakan untuk membuat gambar melingkar, tombol, dan kontrol lainnya:
Membuat Perutean BersamaEffect
Kelas efek harus dibuat di proyek bersama untuk membuat efek lintas platform. Aplikasi sampel membuat kelas kosong RoundEffect
yang berasal dari RoutingEffect
kelas :
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
Kelas ini memungkinkan proyek bersama untuk menyelesaikan referensi efek dalam kode atau XAML tetapi tidak menyediakan fungsionalitas apa pun. Efeknya harus memiliki implementasi untuk setiap platform.
Menerapkan efek Android
Proyek platform Android mendefinisikan RoundEffect
kelas yang berasal dari PlatformEffect
. Kelas ini ditandai dengan assembly
atribut yang memungkinkan Xamarin.Forms untuk menyelesaikan kelas efek:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
Platform Android menggunakan konsep OutlineProvider
untuk menentukan tepi kontrol. Proyek sampel mencakup CornerRadiusProvider
kelas yang berasal dari ViewOutlineProvider
kelas :
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);
}
}
Kelas ini menggunakan properti Xamarin.FormsElement
dan Height
instans Width
untuk menghitung radius yang setengah dari dimensi terpendek.
Setelah penyedia kerangka didefinisikan RoundEffect
, kelas dapat menggunakannya untuk mengimplementasikan efek:
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;
}
}
}
Metode OnAttached
ini dipanggil ketika efek dilampirkan ke elemen. Objek yang OutlineProvider
ada disimpan sehingga dapat dipulihkan ketika efek dilepaskan. Instans CornerRadiusOutlineProvider
baru digunakan sebagai OutlineProvider
dan ClipToOutline
diatur ke true untuk mengklip elemen yang meluap ke batas kerangka.
Metode OnDetatched
ini dipanggil ketika efek dihapus dari elemen dan memulihkan nilai asli OutlineProvider
.
Catatan
Bergantung pada jenis elemen, Control
properti mungkin atau mungkin tidak null. Control
Jika properti tidak null, sudut bulat dapat diterapkan langsung ke kontrol. Namun, jika null, sudut bulat harus diterapkan ke Container
objek. Bidang effectTarget
memungkinkan efek diterapkan ke objek yang sesuai.
Menerapkan efek iOS
Proyek platform iOS mendefinisikan RoundEffect
kelas yang berasal dari PlatformEffect
. Kelas ini ditandai dengan assembly
atribut yang memungkinkan Xamarin.Forms untuk menyelesaikan kelas efek:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
Di iOS, kontrol memiliki Layer
properti , yang memiliki CornerRadius
properti . Implementasi RoundEffect
kelas pada iOS menghitung radius sudut yang sesuai dan memperbarui properti lapisan 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;
}
}
Metode CalculateRadius
menghitung radius berdasarkan dimensi Xamarin.FormsElement
minimum . Metode OnAttached
ini dipanggil ketika efek dilampirkan ke kontrol, dan memperbarui properti lapisan CornerRadius
. Ini mengatur ClipToBounds
properti agar true
elemen yang meluap dipotong ke batas kontrol. Metode OnDetatched
ini dipanggil ketika efek dihapus dari kontrol dan membalikkan perubahan ini, memulihkan radius sudut asli.
Catatan
Bergantung pada jenis elemen, Control
properti mungkin atau mungkin tidak null. Control
Jika properti tidak null, sudut bulat dapat diterapkan langsung ke kontrol. Namun, jika null, sudut bulat harus diterapkan ke Container
objek. Bidang effectTarget
memungkinkan efek diterapkan ke objek yang sesuai.
Mengonsumsi efek
Setelah efek diimplementasikan di seluruh platform, efek tersebut dapat dikonsumsi oleh Xamarin.Forms kontrol. Aplikasi umum dari RoundEffect
membuat objek melingkar Image
. XAML berikut menunjukkan efek yang diterapkan ke Image
instans:
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
Efeknya juga dapat diterapkan dalam kode:
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
Kelas RoundEffect
dapat diterapkan ke kontrol apa pun yang berasal dari VisualElement
.
Catatan
Agar efek menghitung radius yang benar, kontrol yang diterapkannya harus memiliki ukuran eksplisit. Oleh karena itu, HeightRequest
properti dan WidthRequest
harus didefinisikan. Jika kontrol yang terpengaruh muncul dalam StackLayout
, propertinya HorizontalOptions
tidak boleh menggunakan salah satu nilai Perluas seperti LayoutOptions.CenterAndExpand
atau tidak akan memiliki dimensi yang akurat.