在 Xamarin 表单中像边框一样围绕元素创建 Skiasharp 路径
Create Skiasharp path around element like a border in Xamarin forms
我的 Xamarin Forms 应用程序中有一个控件。现在我想围绕它构建一个自定义进度条,比如边框倒计时。但是为了开始,我需要知道如何将它正确地定位在我的元素(viewrenderer)周围,就像一个完整的边框。我可以成功创建边框对象,但是对象的放置不正确。
我所做的是从我的元素中收集 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 路径?
一个简单直接的解决方案是将 Skia 元素和您的按钮置于相同的网格布局中。然后给另一个元素一个合理大小的边距,并以某种方式绘制你的路径,它覆盖视图布局后获得的免费 space:
<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 canvas 的宽度和高度
我的 Xamarin Forms 应用程序中有一个控件。现在我想围绕它构建一个自定义进度条,比如边框倒计时。但是为了开始,我需要知道如何将它正确地定位在我的元素(viewrenderer)周围,就像一个完整的边框。我可以成功创建边框对象,但是对象的放置不正确。
我所做的是从我的元素中收集 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 路径?
一个简单直接的解决方案是将 Skia 元素和您的按钮置于相同的网格布局中。然后给另一个元素一个合理大小的边距,并以某种方式绘制你的路径,它覆盖视图布局后获得的免费 space:
<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 canvas 的宽度和高度