Создайте Skiasharp путь вокруг элемента, как границы в формах Xamarin - PullRequest
0 голосов
/ 07 ноября 2018

В моем приложении Xamarin Forms есть элемент управления. Теперь я хочу построить собственный индикатор выполнения, например, отсчет границы. Но для начала мне нужно знать, как правильно расположить это вокруг моего элемента (наблюдателя), как полную границу. Я могу успешно создать граничный объект, но его размещение неверно.

Что я делаю, так это то, что я собираю X, Y, Width и Height из моего элемента, но когда я добавляю к этому точку останова, она не дает мне никаких полезных и точных чисел. И это показано при развертывании, объект 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-путь элемента управления view?

1 Ответ

0 голосов
/ 07 ноября 2018

Простым и понятным решением было бы поместить элемент 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, чтобы он оставался активным (если вы используете, например, кнопку).

При рисовании вашего пути у вас уже должны быть ширина и высота холста skia в e.Info

...