与 Xamarin.Forms 集成
创建响应触摸和 Xamarin.Forms 元素的 SkiaSharp 图形
SkiaSharp 图形可以通过多种方式与 Xamarin.Forms 的其余部分集成。 可以将 SkiaSharp 画布和 Xamarin.Forms 元素合并在同一页上,甚至可以将 Xamarin.Forms 元素放置在 SkiaSharp 画布的之上:
在 Xamarin.Forms 中创建交互式 SkiaSharp 图形的另一种方法是通过触摸。
示例程序中的第二页标题为“点击切换填充”。 它用两种方式绘制一个简单的圆圈 - 无填充和有填充 - 点击即可切换。 TapToggleFillPage
类演示如何更改 SkiaSharp 图形以响应用户输入。
对于此页面,SKCanvasView
类会在 TapToggleFill.xaml 文件中实例化,该文件还会在视图上设置 Xamarin.FormsTapGestureRecognizer
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="SkiaSharpFormsDemos.TapToggleFillPage"
Title="Tap Toggle Fill">
<skia:SKCanvasView PaintSurface="OnCanvasViewPaintSurface">
<skia:SKCanvasView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnCanvasViewTapped" />
</skia:SKCanvasView.GestureRecognizers>
</skia:SKCanvasView>
</ContentPage>
请注意 skia
XML 命名空间声明。
TapGestureRecognizer
对象的 Tapped
处理程序只需切换布尔字段的值并调用 SKCanvasView
的 InvalidateSurface
方法:
bool showFill = true;
...
void OnCanvasViewTapped(object sender, EventArgs args)
{
showFill ^= true;
(sender as SKCanvasView).InvalidateSurface();
}
对 InvalidateSurface
的调用会有效地生成对 PaintSurface
处理程序的调用,该处理程序使用 showFill
字段来填充或不填充圆圈:
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = Color.Red.ToSKColor(),
StrokeWidth = 50
};
canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
if (showFill)
{
paint.Style = SKPaintStyle.Fill;
paint.Color = SKColors.Blue;
canvas.DrawCircle(info.Width / 2, info.Height / 2, 100, paint);
}
}
StrokeWidth
属性已设置为 50,以强调差异。 还可以先绘制内部,然后再绘制轮廓来查看整个线条宽度。 默认情况下,稍后在 PaintSurface
事件处理程序中绘制的图形会掩盖之前在处理程序中绘制的图形。
“颜色探索”页面演示了如何将 SkiaSharp 图形与其他 Xamarin.Forms 元素集成,并演示了在 SkiaSharp 中定义颜色的两种替代方法之间的差异。 静态 SKColor.FromHsl
方法基于“色调-饱和度-亮度”模型创建 SKColor
值:
public static SKColor FromHsl (Single h, Single s, Single l, Byte a)
静态 SKColor.FromHsv
方法基于类似的“色调-饱和度-值”模型创建 SKColor
值:
public static SKColor FromHsv (Single h, Single s, Single v, Byte a)
在这两种情况下,参数 h
的范围均为 0 到 360。 s
、l
和 v
参数的范围为 0 到 100。 a
(alpha 或不透明度)参数的范围为 0 到 255。
ColorExplorePage.xaml 文件与 Slider
和 Label
视图会并排在 StackLayout
中创建两个 SKCanvasView
对象,允许用户选择 HSL 和 HSV 颜色值:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="SkiaSharpFormsDemos.Basics.ColorExplorePage"
Title="Color Explore">
<StackLayout>
<!-- Hue slider -->
<Slider x:Name="hueSlider"
Maximum="360"
Margin="20, 0"
ValueChanged="OnSliderValueChanged" />
<Label HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference hueSlider},
Path=Value,
StringFormat='Hue = {0:F0}'}" />
<!-- Saturation slider -->
<Slider x:Name="saturationSlider"
Maximum="100"
Margin="20, 0"
ValueChanged="OnSliderValueChanged" />
<Label HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference saturationSlider},
Path=Value,
StringFormat='Saturation = {0:F0}'}" />
<!-- Lightness slider -->
<Slider x:Name="lightnessSlider"
Maximum="100"
Margin="20, 0"
ValueChanged="OnSliderValueChanged" />
<Label HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference lightnessSlider},
Path=Value,
StringFormat='Lightness = {0:F0}'}" />
<!-- HSL canvas view -->
<Grid VerticalOptions="FillAndExpand">
<skia:SKCanvasView x:Name="hslCanvasView"
PaintSurface="OnHslCanvasViewPaintSurface" />
<Label x:Name="hslLabel"
HorizontalOptions="Center"
VerticalOptions="Center"
BackgroundColor="Black"
TextColor="White" />
</Grid>
<!-- Value slider -->
<Slider x:Name="valueSlider"
Maximum="100"
Margin="20, 0"
ValueChanged="OnSliderValueChanged" />
<Label HorizontalTextAlignment="Center"
Text="{Binding Source={x:Reference valueSlider},
Path=Value,
StringFormat='Value = {0:F0}'}" />
<!-- HSV canvas view -->
<Grid VerticalOptions="FillAndExpand">
<skia:SKCanvasView x:Name="hsvCanvasView"
PaintSurface="OnHsvCanvasViewPaintSurface" />
<Label x:Name="hsvLabel"
HorizontalOptions="Center"
VerticalOptions="Center"
BackgroundColor="Black"
TextColor="White" />
</Grid>
</StackLayout>
</ContentPage>
这两个 SKCanvasView
元素位于单个单元格 Grid
中,顶部有一个 Label
,用于显示生成的 RGB 颜色值。
ColorExplorePage.xaml.cs 代码隐藏文件相对简单。 三个 Slider
元素的共享 ValueChanged
处理程序会使两个 SKCanvasView
元素失效。 PaintSurface
处理程序使用 Slider
元素指示的颜色清除画布,并会设置位于 SKCanvasView
元素顶部的 Label
:
public partial class ColorExplorePage : ContentPage
{
public ColorExplorePage()
{
InitializeComponent();
hueSlider.Value = 0;
saturationSlider.Value = 100;
lightnessSlider.Value = 50;
valueSlider.Value = 100;
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
hslCanvasView.InvalidateSurface();
hsvCanvasView.InvalidateSurface();
}
void OnHslCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKColor color = SKColor.FromHsl((float)hueSlider.Value,
(float)saturationSlider.Value,
(float)lightnessSlider.Value);
args.Surface.Canvas.Clear(color);
hslLabel.Text = String.Format(" RGB = {0:X2}-{1:X2}-{2:X2} ",
color.Red, color.Green, color.Blue);
}
void OnHsvCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKColor color = SKColor.FromHsv((float)hueSlider.Value,
(float)saturationSlider.Value,
(float)valueSlider.Value);
args.Surface.Canvas.Clear(color);
hsvLabel.Text = String.Format(" RGB = {0:X2}-{1:X2}-{2:X2} ",
color.Red, color.Green, color.Blue);
}
}
在 HSL 和 HSV 颜色模型中,色调值范围为 0 到 360,并会指示颜色的主导色调。 这些是彩虹的传统颜色:红色、橙色、黄色、绿色、蓝色、靛蓝色、紫罗兰色,并会循环回红色。
在 HSL 模型中,亮度的 0 值始终为黑色,100 值始终为白色。 当饱和度值为 0 时,0 到 100 之间的亮度值为不同的灰色。 增加饱和度会增加更多颜色。 当饱和度为 100,亮度为 50 时,会出现纯色(即 RGB 值中一个分量等于 255,另一个分量等于 0,第三个分量在 0 到 255 之间)。
在 HSV 模型中,纯色会在饱和度和值均为 100 时产生。 如果值为 0,不论其他设置如何,颜色均为黑色。 当饱和度为 0 且值范围为 0 到 100 时,会出现灰色阴影。
但是,了解这两种模式的最佳方法是亲自尝试: