【问题标题】:Create Skiasharp path around element like a border in Xamarin forms围绕元素创建 Skiasharp 路径,例如 Xamarin 表单中的边框
【发布时间】:2018-11-07 20:30:40
【问题描述】:

我的 Xamarin Forms 应用程序中有一个控件。现在我希望在它周围建立一个自定义进度条,比如边框倒计时。但要开始做事,我需要知道如何在我的元素(视图渲染器)周围正确定位它,就像一个完整的边框。我可以成功创建一个边框对象,但是对象的放置不正确。

我所做的是从我的元素中收集 X、Y、宽度和高度,但是当我为此添加断点时,它似乎没有给我任何有用和准确的数字。并且在我部署时显示,skiasharp 对象未按应有的方式对齐。

这就是我的工作:

public class SvgPathCountdown : SKCanvasView
{

    public SvgPathCountdown()
    {
        this.InvalidateSurface();
    }

    private static void OnPropertyChanged(BindableObject bindable, object oldVal, object newVal)
    {
        var svgPath = bindable as SvgPathCountdown;
        svgPath?.InvalidateSurface();
    }

    public static readonly BindableProperty XValueProperty =
        BindableProperty.Create(nameof(XValue), typeof(double), typeof(SvgPathCountdown), 10.0, propertyChanged: OnPropertyChanged);

    public double XValue
    {
        get { return (double)GetValue(XValueProperty); }
        set { SetValue(XValueProperty, value); }
    }

    public static readonly BindableProperty YValueProperty =
        BindableProperty.Create(nameof(YValue), typeof(double), typeof(SvgPathCountdown), 10.0, propertyChanged: OnPropertyChanged);

    public double YValue
    {
        get { return (double)GetValue(YValueProperty); }
        set { SetValue(YValueProperty, value); }
    }

    public static readonly BindableProperty WidthValueProperty =
        BindableProperty.Create(nameof(WidthValue), typeof(double), typeof(SvgPathCountdown), 10.0, propertyChanged: OnPropertyChanged);


    public double WidthValue
    {
        get { return (double)GetValue(WidthValueProperty); }
        set { SetValue(WidthValueProperty, value); }
    }

    public static readonly BindableProperty HeightValueProperty =
        BindableProperty.Create(nameof(HeightValue), typeof(double), typeof(SvgPathCountdown), 10.0, propertyChanged: OnPropertyChanged);


    public double HeightValue
    {
        get { return (double)GetValue(HeightValueProperty); }
        set { SetValue(HeightValueProperty, value); }
    }


    protected override void OnPaintSurface(SKPaintSurfaceEventArgs args)
    {

        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKRect bounds;

        var rect = SKRect.Create((float)XValue, (float)YValue, (float)WidthValue, (float)HeightValue);


        var paint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.Blue,
            StrokeWidth = 10,
            StrokeCap = SKStrokeCap.Round,
            StrokeJoin = SKStrokeJoin.Round
        };

        // draw fill
        canvas.DrawRect(rect, paint);

        // change the brush (stroke with red)
        paint.Style = SKPaintStyle.Stroke;
        paint.Color = SKColors.Red;

        // draw stroke
        canvas.DrawRect(rect, paint);

    }

还有 XAML:

<controls:CustomElement x:Name = "myControlElement" AbsoluteLayout.LayoutBounds="0.5, 0.2, 0.85, 0.2" AbsoluteLayout.LayoutFlags="All" />

<controls:SvgPathCountdown x:Name = "svgPath" />

这里的代码我设置了值:

 svgPath.XValue = myControlElement.X;
 svgPath.YValue = myControlElement.Y;
 svgPath.WidthValue = myControlElement.AnchorX;
 svgPath.HeightValue = myControlElement.HeightRequest;

当我使用后面代码中的设置值执行SKRect.Create 时,如何调整我的代码使其与元素匹配?也许我能以某种方式获得视图控件的 svg 路径?

【问题讨论】:

    标签: c# xamarin xamarin.forms skiasharp


    【解决方案1】:

    一个简单直接的解决方案是将 Skia 元素和您的按钮放入相同的网格布局中。然后给另一个元素一个合理大小的边距并以某种方式绘制路径,以覆盖视图布局后获得的可用空间:

    <Grid AbsoluteLayout.LayoutBounds="0.5, 0.2, 0.85, 0.2" AbsoluteLayout.LayoutFlags="All">
        <controls:SvgPathCountdown x:Name = "svgPath" />
        <controls:CustomElement x:Name = "myControlElement" Margin="5,5,5,5" />
    </Grid>
    

    还要确保将元素放置在 Skia Path 元素之后,以防止它被skia 元素覆盖,使其保持可点击状态(如果您使用例如按钮)。

    在绘制路径时,您应该已经在 e.Info 中获得了 skia 画布的宽度和高度

    【讨论】:

    • 好的!在SKRect.Create 中,我应该输入什么值?
    • 如果我在创建中添加了var rect = SKRect.Create((float)this.X, (float)this.Y, (float)this.Width*2, (float)this.Height*2);,那么它会完美对齐。但是仍然很困惑为什么我需要将高度+宽度值加倍..
    • SKRect.Create(1,1, e.Info.Width-2, e.Info.Heigh -2) 将导致在距离滑雪板的实际框架边界 1 个单位的位置绘制一个矩形画布。
    • 不客气!很高兴听到这解决了问题。
    • 仅供参考:xamarin 中使用的高度或宽度值是与设备无关的单位。这意味着生成的宽度将取决于您设备的屏幕密度,例如xamarin 中的宽度值 300 将在具有视网膜屏幕 (@2x) 的设备上产生 150 个实际单位的宽度。 Skia 也使用自己的单位系统,因此如果您需要进行一些计算,请始终使用存储在 e.Info 中的值。
    猜你喜欢
    • 2021-12-31
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    相关资源
    最近更新 更多