Xamarin.Forms 재사용 가능한 RoundEffect
Important
더 이상 RoundEffect
를 사용하여 컨트롤을 원으로 렌더링할 필요가 없습니다. EllipseGeometry
를 사용하여 컨트롤을 잘라 내는 것이 가장 좋습니다. 자세한 내용은 기하 도형으로 잘라 내기를 참조하세요.
RoundEffect는 VisualElement
에서 파생되는 모든 컨트롤을 원으로 렌더링하는 작업을 간소화합니다. 이 효과는 원형 이미지, 단추 및 기타 컨트롤을 만드는 데 사용할 수 있습니다.
공유 RoutingEffect 만들기
플랫폼 간 효과를 만들려면 공유 프로젝트에 효과 클래스를 만들어야 합니다. 샘플 애플리케이션은 RoutingEffect
클래스에서 파생된 빈 RoundEffect
클래스를 만듭니다.
public class RoundEffect : RoutingEffect
{
public RoundEffect() : base($"Xamarin.{nameof(RoundEffect)}")
{
}
}
이 클래스는 공유 프로젝트가 코드 또는 XAML에 있는 효과에 대한 참조를 확인할 수 있도록 하지만 기능은 제공하지 않습니다. 효과에는 각 플랫폼별 구현이 있어야 합니다.
Android 효과 구현
Android 플랫폼 프로젝트는 PlatformEffect
에서 파생된 RoundEffect
클래스를 정의합니다. 이 클래스는 Xamarin.Forms가 효과 클래스를 확인할 수 있는 assembly
특성으로 태그가 지정되었습니다.
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.Droid.RoundEffect), nameof(RoundEffectDemo.Droid.RoundEffect))]
namespace RoundEffectDemo.Droid
{
public class RoundEffect : PlatformEffect
{
// ...
}
}
Android 플랫폼은 OutlineProvider
개념을 사용하여 컨트롤의 가장자리를 정의합니다. 샘플 프로젝트에는 ViewOutlineProvider
클래스에서 파생된 CornerRadiusProvider
클래스가 포함됩니다.
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
의 새로운 인스턴스가 OutlineProvider
로 사용되고, 오버플로 요소를 윤곽 테두리에 맞게 자르기 위해 ClipToOutline
이 true로 설정됩니다.
OnDetatched
메서드는 요소에서 효과가 제거될 경우 호출되어 원래 OutlineProvider
값을 복원합니다.
참고 항목
요소 유형에 따라 Control
속성은 Null이거나 Null이 아닐 수 있습니다. Control
속성이 Null이 아니면 컨트롤에 직접 동근 모퉁이를 적용할 수 있습니다. 그러나 이 속성이 Null이면 둥근 모퉁이를 Container
개체에 적용해야 합니다. effectTarget
필드를 사용하여 적절한 개체에 효과를 적용할 수 있습니다.
iOS 효과 구현
iOS 플랫폼 프로젝트는 PlatformEffect
에서 파생된 RoundEffect
클래스를 정의합니다. 이 클래스는 Xamarin.Forms가 효과 클래스를 확인할 수 있는 assembly
특성으로 태그가 지정되었습니다.
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(RoundEffectDemo.iOS.RoundEffect), nameof(RoundEffectDemo.iOS.RoundEffect))]
namespace RoundEffectDemo.iOS
{
public class RoundEffect : PlatformEffect
{
// ...
}
iOS에서 컨트롤은 Layer
속성을 가지며, 여기에는 CornerRadius
속성이 있습니다. iOS의 RoundEffect
클래스 구현은 적절한 모퉁이 반경을 계산하여 계층의 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이거나 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
속성은 LayoutOptions.CenterAndExpand
와 같은 Expand 값에 사용되어서는 안 됩니다. 그렇지 않으면 정확한 크기를 갖지 않게 됩니다.