diff --git a/Handlers/BoxViewHandler.cs b/Handlers/BoxViewHandler.cs index 6b9ddd5..3bfe042 100644 --- a/Handlers/BoxViewHandler.cs +++ b/Handlers/BoxViewHandler.cs @@ -34,17 +34,13 @@ public partial class BoxViewHandler : ViewHandler { if (boxView.Color != null) { - handler.PlatformView.Color = new SKColor( - (byte)(boxView.Color.Red * 255), - (byte)(boxView.Color.Green * 255), - (byte)(boxView.Color.Blue * 255), - (byte)(boxView.Color.Alpha * 255)); + handler.PlatformView.Color = boxView.Color; } } public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView) { - handler.PlatformView.CornerRadius = (float)boxView.CornerRadius.TopLeft; + handler.PlatformView.CornerRadius = boxView.CornerRadius; } public static void MapBackground(BoxViewHandler handler, BoxView boxView) diff --git a/Views/SkiaBoxView.cs b/Views/SkiaBoxView.cs index e33fb0f..d0d6e40 100644 --- a/Views/SkiaBoxView.cs +++ b/Views/SkiaBoxView.cs @@ -2,47 +2,100 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Maui.Controls; +using Microsoft.Maui.Graphics; using SkiaSharp; namespace Microsoft.Maui.Platform; /// /// Skia-rendered BoxView - a simple colored rectangle. +/// Implements MAUI IBoxView interface patterns. /// public class SkiaBoxView : SkiaView { + #region BindableProperties + public static readonly BindableProperty ColorProperty = - BindableProperty.Create(nameof(Color), typeof(SKColor), typeof(SkiaBoxView), SKColors.Transparent, + BindableProperty.Create(nameof(Color), typeof(Color), typeof(SkiaBoxView), Colors.Transparent, BindingMode.TwoWay, propertyChanged: (b, o, n) => ((SkiaBoxView)b).Invalidate()); public static readonly BindableProperty CornerRadiusProperty = - BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaBoxView), 0f, + BindableProperty.Create(nameof(CornerRadius), typeof(CornerRadius), typeof(SkiaBoxView), new CornerRadius(0), BindingMode.TwoWay, propertyChanged: (b, o, n) => ((SkiaBoxView)b).Invalidate()); - public SKColor Color + #endregion + + #region Properties + + public Color Color { - get => (SKColor)GetValue(ColorProperty); + get => (Color)GetValue(ColorProperty); set => SetValue(ColorProperty, value); } - public float CornerRadius + public CornerRadius CornerRadius { - get => (float)GetValue(CornerRadiusProperty); + get => (CornerRadius)GetValue(CornerRadiusProperty); set => SetValue(CornerRadiusProperty, value); } + #endregion + + #region Helper Methods + + /// + /// Converts a MAUI Color to SkiaSharp SKColor. + /// + private static SKColor ToSKColor(Color? color) + { + if (color == null) return SKColors.Transparent; + return new SKColor( + (byte)(color.Red * 255), + (byte)(color.Green * 255), + (byte)(color.Blue * 255), + (byte)(color.Alpha * 255)); + } + + #endregion + + #region Drawing + protected override void OnDraw(SKCanvas canvas, SKRect bounds) { + SKColor fillColor = ToSKColor(Color); + using var paint = new SKPaint { - Color = Color, + Color = fillColor, Style = SKPaintStyle.Fill, IsAntialias = true }; - if (CornerRadius > 0) + // Check if any corner radius is set + var cr = CornerRadius; + bool hasRadius = cr.TopLeft > 0 || cr.TopRight > 0 || cr.BottomLeft > 0 || cr.BottomRight > 0; + + if (hasRadius) { - canvas.DrawRoundRect(bounds, CornerRadius, CornerRadius, paint); + // Check if all corners are the same (uniform radius) + if (cr.TopLeft == cr.TopRight && cr.TopRight == cr.BottomRight && cr.BottomRight == cr.BottomLeft) + { + canvas.DrawRoundRect(bounds, (float)cr.TopLeft, (float)cr.TopLeft, paint); + } + else + { + // Different corner radii - use SKRoundRect with individual radii + var radii = new SKPoint[] + { + new SKPoint((float)cr.TopLeft, (float)cr.TopLeft), + new SKPoint((float)cr.TopRight, (float)cr.TopRight), + new SKPoint((float)cr.BottomRight, (float)cr.BottomRight), + new SKPoint((float)cr.BottomLeft, (float)cr.BottomLeft) + }; + var roundRect = new SKRoundRect(); + roundRect.SetRectRadii(bounds, radii); + canvas.DrawRoundRect(roundRect, paint); + } } else { @@ -50,6 +103,10 @@ public class SkiaBoxView : SkiaView } } + #endregion + + #region Measurement + protected override SKSize MeasureOverride(SKSize availableSize) { // BoxView uses explicit size or a default size when in unbounded context @@ -64,4 +121,6 @@ public class SkiaBoxView : SkiaView return new SKSize(width, height); } + + #endregion }