Xamarin.Forms 可重複使用的 RoundEffect
重要
不再需要使用 RoundEffect
將控件轉譯為圓形。 最新的建議方法是使用 EllipseGeometry
來裁剪控件。 如需詳細資訊,請參閱 使用 Geometry 裁剪。
RoundEffect 可簡化轉譯任何衍生自 VisualElement
做為圓形的控件。 這個效果可用來建立迴圈影像、按鈕和其他控件:
建立共用 RoutingEffect
必須在共享專案中建立效果類別,才能建立跨平臺效果。 範例應用程式會建立衍生自 類別的RoutingEffect
空白RoundEffect
類別:
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
這個類別可讓共用專案解析程序代碼或 XAML 中效果的參考,但不提供任何功能。 效果必須具有每個平台的實作。
實作Android效果
Android 平台專案會 RoundEffect
定義衍生自 PlatformEffect
的類別。 這個類別會以 assembly
允許 Xamarin.Forms 解析效果類別的屬性標記:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
Android 平臺會使用的概念 OutlineProvider
來定義控件的邊緣。 範例專案包含 CornerRadiusProvider
衍生自 類別的 ViewOutlineProvider
類別:
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);
}
}
這個類別會使用 Width
實例的 Xamarin.FormsElement
和 Height
屬性來計算最小維度的一半半徑。
定義大綱提供者之後, RoundEffect
類別就可以取用它來實作效果:
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
效果附加至專案時,會呼叫 方法。 現有的 OutlineProvider
物件會儲存,以便在卸離效果時還原它。 的新實例CornerRadiusOutlineProvider
會當做 ,並ClipToOutline
設定為 OutlineProvider
true,將溢位元素裁剪到外框線。
從 OnDetatched
項目移除效果並還原原始 OutlineProvider
值時,會呼叫 方法。
注意
視專案類型而定, Control
屬性可能或可能不是 Null。 Control
如果 屬性不是 Null,則可以將圓角直接套用至 控件。 不過,如果它是 Null,則必須將圓角套用至 Container
物件。 欄位 effectTarget
允許將效果套用至適當的物件。
實作 iOS 效果
iOS 平台專案會 RoundEffect
定義衍生自 PlatformEffect
的類別。 這個類別會以 assembly
允許 Xamarin.Forms 解析效果類別的屬性標記:
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
在 iOS 上,控制件具有 Layer
屬性的屬性 CornerRadius
。 RoundEffect
iOS 上的類別實作會計算適當的圓角半徑,並更新圖層的 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;
}
}
方法 CalculateRadius
會根據的 Xamarin.FormsElement
最小維度計算半徑。 當 OnAttached
效果附加至控件時,會呼叫 方法,並更新層次的 CornerRadius
屬性。 它會將 ClipToBounds
屬性設定為 , true
讓溢位的專案裁剪到控件的框線。 OnDetatched
從控件移除效果並反轉這些變更時,會呼叫 方法,以還原原始圓角半徑。
注意
視專案類型而定, Control
屬性可能或可能不是 Null。 Control
如果 屬性不是 Null,則可以將圓角直接套用至 控件。 不過,如果它是 Null,則必須將圓角套用至 Container
物件。 欄位 effectTarget
允許將效果套用至適當的物件。
取用效果
一旦跨平台實作效果,控件就可以取用 Xamarin.Forms 效果。 的 RoundEffect
常見應用程式是讓 Image
物件迴圈。 下列 XAML 顯示套用至 Image
實例的效果:
<Image Source=outdoors"
HeightRequest="100"
WidthRequest="100">
<Image.Effects>
<local:RoundEffect />
</Image.Effects>
</Image>
效果也可以在程式代碼中套用:
var image = new Image
{
Source = ImageSource.FromFile("outdoors"),
HeightRequest = 100,
WidthRequest = 100
};
image.Effects.Add(new RoundEffect());
類別 RoundEffect
可以套用至衍生自 VisualElement
的任何控件。
注意
若要讓效果計算正確的半徑,套用至的控件必須具有明確的重設大小。 因此, HeightRequest
應該定義 和 WidthRequest
屬性。 如果受影響的控件出現在 中 StackLayout
,則其 HorizontalOptions
屬性不應該使用其中一個 Expand 值,例如 LayoutOptions.CenterAndExpand
,否則其不會有精確的維度。