SkiaSharp 1.68.2 Xamarin.Forms GTK 视图层 API 全解:SKCanvasView/SKGLView、ImageSource 桥接与触摸事件体系

发布时间:2026/10/16 17:34:53
SkiaSharp 1.68.2 Xamarin.Forms GTK 视图层 API 全解:SKCanvasView/SKGLView、ImageSource 桥接与触摸事件体系
图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载本文基于 SkiaSharp 仓库中 SkiaSharp.Views.Forms.dll 的 1.68.2 API diff 文档 展开面向在 Xamarin.Forms 中集成 SkiaSharp 渲染、尤其是使用 GTK 桌面后端的开发者。文章完整梳理SkiaSharp.Views.Forms命名空间在 1.68.2 版中的全部公开类型与成员并结合仓库内共享源码、GTK 视图实现与发布说明解释SKCanvasView/SKGLView的绘制模型、触摸事件参数、ImageSource子类桥接、类型转换扩展及渲染器的工作原理。读完本文你将能够准确理解 1.68.x 时代 Xamarin.Forms SkiaSharp 视图层的 API 布局并能依据 API 签名与源码路径在自己的应用中正确使用这些控件与事件参数。背景1.68.2 为 Xamarin.Forms 带来 GTK 视图后端SkiaSharp 1.68.2 是 2020 年 4 月 30 日发布的稳定版本见 1.68.2 发布说明其 Platform 章节明确记载了本次引入的两项关键平台工作为 Xamarin.Forms 增加 GTK 视图后端对应 PR #1089将捆绑的 Xamarin.Forms 基线更新到 4.2.0.910310并始终引用 netstandard 以保证下游目标解析一致对应 PR #1109、#1250。本文所讨论的 API diff 文档正是该 GTK 后端对应的程序集SkiaSharp.Views.Forms.dllGTK 变体的完整 API 表面。整个SkiaSharp.Views.Forms命名空间在 1.68.2 中均为新引入程序集版本由 0.0.0.0 变更为 1.68.0.0。同一版本的其余平台 diff 可参见 1.68.2 API 变更索引其中将SkiaSharp.Views.Forms本体标记为 ⚠️ breaking而 GTK 变体为新增。适用前提说明SkiaSharp.Views.Forms属于 Xamarin.Forms 时代的绑定层。从仓库 packages.md 中的包映射表 可见后续版本中SkiaSharp.Views.Forms由SkiaSharp.Views.Maui.Controls取代、SkiaSharp.Views.Forms.GTK由SkiaSharp.Views.Gtk3取代。本文所有 API 签名均以 1.68.2 实际发布的程序集为准。核心视图控件SKCanvasView 与 SKGLView该命名空间的灵魂是两套可直接放入 Xamarin.Forms 页面Xamarin.Forms.View子类的渲染控件分别对应 CPU 光栅化与 OpenGL 硬件加速两条渲染路径。SKCanvasViewCPU 光栅化视图public class SKCanvasView : Xamarin.Forms.View, ISKCanvasViewController, System.ComponentModel.INotifyPropertyChanged, Xamarin.Forms.IAnimatable, Xamarin.Forms.IElementController, Xamarin.Forms.IGestureRecognizers, Xamarin.Forms.ITabStopElement, Xamarin.Forms.IViewController, Xamarin.Forms.IVisualElementController, Xamarin.Forms.Internals.IDynamicResourceHandler, Xamarin.Forms.Internals.IGestureController, Xamarin.Forms.Internals.INameScope, Xamarin.Forms.Internals.INavigationProxy { public SKCanvasView (); public static Xamarin.Forms.BindableProperty EnableTouchEventsProperty; public static Xamarin.Forms.BindableProperty IgnorePixelScalingProperty; public SkiaSharp.SKSize CanvasSize { get; } public bool EnableTouchEvents { get; set; } public bool IgnorePixelScaling { get; set; } public event System.EventHandlerSKPaintSurfaceEventArgs PaintSurface; public event System.EventHandlerSKTouchEventArgs Touch; public void InvalidateSurface (); protected override Xamarin.Forms.SizeRequest OnMeasure (double widthConstraint, double heightConstraint); protected virtual void OnPaintSurface (SKPaintSurfaceEventArgs e); protected virtual void OnTouch (SKTouchEventArgs e); }关键成员语义CanvasSize只读当前画布的像素尺寸。注意画布尺寸可能不同于视图尺寸——它受设备像素密度影响与 GTK 原生视图 SKDrawingArea.CanvasSize 的文档说明一致The canvas size may be different to the view size as a result of the current devices pixel density.EnableTouchEvents布尔值决定是否启用触摸/鼠标事件分发。置为true后Touch事件才会被触发。IgnorePixelScaling布尔值置为true时忽略设备像素密度以逻辑像素为单位进行绘制。PaintSurface事件与OnPaintSurface虚方法两种绘制入口。继承自SKCanvasView时若覆写OnPaintSurface需调用base.OnPaintSurface(e)以继续触发事件——这一约定在 GTK 原生视图 SKDrawingArea 的文档注释 中被明确强调。InvalidateSurface()请求重绘。1.68.2 的发布说明提到本版本对视图生命周期与重绘做了整体重构PR #1180、#1213修复了排队重绘与重复加载问题。SKGLViewOpenGL 硬件加速视图public class SKGLView : Xamarin.Forms.View, ISKGLViewController, /* ...同 SKCanvasView 的接口列表... */ { public SKGLView (); public static Xamarin.Forms.BindableProperty EnableTouchEventsProperty; public static Xamarin.Forms.BindableProperty HasRenderLoopProperty; public SkiaSharp.SKSize CanvasSize { get; } public bool EnableTouchEvents { get; set; } public SkiaSharp.GRContext GRContext { get; } public bool HasRenderLoop { get; set; } public event System.EventHandlerSKPaintGLSurfaceEventArgs PaintSurface; public event System.EventHandlerSKTouchEventArgs Touch; public void InvalidateSurface (); protected override Xamarin.Forms.SizeRequest OnMeasure (double widthConstraint, double heightConstraint); protected virtual void OnPaintSurface (SKPaintGLSurfaceEventArgs e); protected virtual void OnTouch (SKTouchEventArgs e); }与SKCanvasView的差异集中在两点GRContext只读当前 OpenGL 上下文对应的 SkiaGRContext可用于在绘制前创建 GPU 资源纹理、图像等HasRenderLoop连续渲染模式开关。置为true时视图进入持续重绘的渲染循环适合动画/实时场景false时仅按需重绘InvalidateSurface或系统触发。视图控制器接口两个视图分别通过ISKCanvasViewController与ISKGLViewController暴露内部契约供渲染器与视图之间通信public interface ISKCanvasViewController : Xamarin.Forms.IElementController, Xamarin.Forms.IViewController, Xamarin.Forms.IVisualElementController { public event System.EventHandlerSkiaSharp.Views.Forms.GetPropertyValueEventArgsSkiaSharp.SKSize GetCanvasSize; public event System.EventHandler SurfaceInvalidated; public virtual void OnPaintSurface (SKPaintSurfaceEventArgs e); public virtual void OnTouch (SKTouchEventArgs e); } public interface ISKGLViewController : Xamarin.Forms.IElementController, Xamarin.Forms.IViewController, Xamarin.Forms.IVisualElementController { public event System.EventHandlerSkiaSharp.Views.Forms.GetPropertyValueEventArgsSkiaSharp.SKSize GetCanvasSize; public event System.EventHandlerSkiaSharp.Views.Forms.GetPropertyValueEventArgsSkiaSharp.GRContext GetGRContext; public event System.EventHandler SurfaceInvalidated; public virtual void OnPaintSurface (SKPaintGLSurfaceEventArgs e); public virtual void OnTouch (SKTouchEventArgs e); }其中GetCanvasSize/GetGRContext属于请求-响应式事件事件参数GetPropertyValueEventArgsT携带可写的Value属性处理方写入值后返回事件发起方即获得结果public class GetPropertyValueEventArgsT : System.EventArgs { public GetPropertyValueEventArgs (); public T Value { get; set; } }绘制事件参数SKPaintSurfaceEventArgs 与 SKPaintGLSurfaceEventArgs两个PaintSurface事件分别使用专用的参数类型它们的源码实现在仓库共享层 source/SkiaSharp.Views/SkiaSharp.Views.Shared/ 中被 iOS/Android/GTK 等各平台复用通过条件编译切换命名空间。SKPaintSurfaceEventArgsCPU 绘制public class SKPaintSurfaceEventArgs : System.EventArgs { public SKPaintSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.SKImageInfo info); // 属性 public SkiaSharp.SKImageInfo Info { get; } public SkiaSharp.SKSurface Surface { get; } }对应源码 SKPaintSurfaceEventArgs.cs 表明单参数构造surface, info实际委托给三参数构造(surface, info, info)并额外暴露了 diff 文档中未列出的RawInfo属性底层表面的真实尺寸与颜色类型。典型用法即从e.Surface.Canvas取画布、以e.Info.Width/Height作为绘制边界。SKPaintGLSurfaceEventArgsGPU 绘制GL 版本的 API 表面更复杂且带有一个已过时的构造重载public class SKPaintGLSurfaceEventArgs : System.EventArgs { public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget); [Obsolete (Use SKPaintGLSurfaceEventArgs(SKSurface, GRBackendRenderTarget, SKColorType, GRSurfaceOrigin) instead.)] public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTargetDesc renderTarget); public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKColorType colorType); public SkiaSharp.GRBackendRenderTarget BackendRenderTarget { get; } public SkiaSharp.SKColorType ColorType { get; } public SkiaSharp.GRSurfaceOrigin Origin { get; } [Obsolete (Use BackendRenderTarget instead.)] public SkiaSharp.GRBackendRenderTargetDesc RenderTarget { get; } public SkiaSharp.SKSurface Surface { get; } }源码层面有三处值得注意的实现细节见 SKPaintGLSurfaceEventArgs.cs默认参数(surface, renderTarget)构造默认使用GRSurfaceOrigin.BottomLeft与SKColorType.Rgba8888创建事件参数废弃轨迹旧版基于GRBackendRenderTargetDesc的构造与RenderTarget属性均被标记[Obsolete]应迁移到GRBackendRenderTarget 显式origin/colorType的重载——这正是 1.68.2 API 演进中 GL 渲染修正确保绘制前 GL 上下文为 currentPR #1141的一部分Info 派生完整构造会由renderTarget.Width/Height与ColorType生成Info即new SKImageInfo(renderTarget.Width, renderTarget.Height, ColorType)。触摸事件体系SKTouchEventArgs 与配套枚举EnableTouchEvents true后Touch事件携带SKTouchEventArgs。该类型在 1.68.2 中加入了来自社区贡献的设备类型与压感支持PR #1191、#1212发布说明中记载为 adding pressure and eraser handling。public class SKTouchEventArgs : System.EventArgs { public SKTouchEventArgs (long id, SKTouchAction type, SkiaSharp.SKPoint location, bool inContact); public SKTouchEventArgs (long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SkiaSharp.SKPoint location, bool inContact); public SKTouchEventArgs (long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SkiaSharp.SKPoint location, bool inContact, int wheelDelta); public SKTouchEventArgs (long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SkiaSharp.SKPoint location, bool inContact, int wheelDelta, float pressure); public SKTouchAction ActionType { get; } public SKTouchDeviceType DeviceType { get; } public bool Handled { get; set; } public long Id { get; } public bool InContact { get; } public SkiaSharp.SKPoint Location { get; } public SKMouseButton MouseButton { get; } public float Pressure { get; } public int WheelDelta { get; } public override string ToString (); }各成员说明成员类型含义Idlong触摸点/指针的唯一标识用于多点触摸时追踪同一触点ActionTypeSKTouchAction当前动作类型按下/移动/释放/进入/退出等LocationSKPoint触点位置逻辑坐标InContactbool是否与表面保持接触MouseButtonSKMouseButton触发的鼠标按键仅鼠标设备有效DeviceTypeSKTouchDeviceType输入设备类型触摸 / 鼠标 / 触控笔Pressurefloat压感值支持压感的设备提供如触控笔WheelDeltaint滚轮增量WPF 等桌面端滚轮事件PR #1079Handledbool可写置为true表示事件已被处理阻止继续传递三个配套枚举[Serializable] public enum SKTouchAction { Entered 0, Pressed 1, Moved 2, Released 3, Cancelled 4, Exited 5, WheelChanged 6, } [Serializable] public enum SKTouchDeviceType { Touch 0, Mouse 1, Pen 2, } [Serializable] public enum SKMouseButton { Unknown 0, Left 1, Middle 2, Right 3, }SKTouchAction覆盖了从触点进入Entered到离开Exited的完整生命周期WheelChanged专门用于桌面端滚轮输入SKMouseButton的Unknown用于非鼠标设备。ImageSource 桥接将 Skia 对象直接作为 Xamarin.Forms 图像源命名空间提供了四个Xamarin.Forms.ImageSource子类使SKBitmap、SKImage、SKPicture、SKPixmap可以直接赋值给Image.Source等属性并配合 GTK 平台的SKImageSourceHandler完成到Gdk.Pixbuf的加载。四个 ImageSource 子类public sealed class SKBitmapImageSource : Xamarin.Forms.ImageSource, System.ComponentModel.INotifyPropertyChanged, /* ...Xamarin.Forms 内部接口... */ { public SKBitmapImageSource (); public static Xamarin.Forms.BindableProperty BitmapProperty; public SkiaSharp.SKBitmap Bitmap { get; set; } public override System.Threading.Tasks.Taskbool Cancel (); protected override void OnPropertyChanged (string propertyName); public static SKBitmapImageSource op_Implicit (SkiaSharp.SKBitmap bitmap); public static SkiaSharp.SKBitmap op_Implicit (SKBitmapImageSource source); } public sealed class SKImageImageSource : Xamarin.Forms.ImageSource { /* Image 属性 双向隐式转换 */ } public sealed class SKPixmapImageSource : Xamarin.Forms.ImageSource { /* Pixmap 属性 双向隐式转换 */ } public sealed class SKPictureImageSource : Xamarin.Forms.ImageSource { public static Xamarin.Forms.BindableProperty DimensionsProperty; public static Xamarin.Forms.BindableProperty PictureProperty; public SkiaSharp.SKSizeI Dimensions { get; set; } public SkiaSharp.SKPicture Picture { get; set; } public static SkiaSharp.SKPicture op_Explicit (SKPictureImageSource source); // 显式转换 }共性设计每个子类都以对应的 Skia 对象为绑定属性BitmapProperty/ImageProperty/PixmapProperty/PictureProperty提供双向隐式转换SKPictureImageSource为显式转换op_Explicit因此可直接书写source bitmap;或SKBitmap bmp imageSource;。SKPictureImageSource额外需要DimensionsSKSizeI来指定矢量图栅格化尺寸。GTK 平台加载器与 breaking 变化public sealed class SKImageSourceHandler : Xamarin.Forms.IRegisterable, Xamarin.Forms.Platform.GTK.Renderers.IImageSourceHandler { public SKImageSourceHandler (); public virtual System.Threading.Tasks.TaskGdk.Pixbuf LoadImageAsync ( Xamarin.Forms.ImageSource imagesource, System.Threading.CancellationToken cancelationToken, float scale); }该处理器负责把上述任意ImageSource子类在 GTK 端异步加载为Gdk.Pixbuf。其底层像素拷贝逻辑可在 GTK 扩展类 GTKExtensions.cs 中找到印证ToPixbuf(this SKImage)创建Colorspace.Rgb带 alpha 的 8 位Pixbuf通过SKPixmap包装像素指针执行ReadPixels并在Bgra8888颜色类型下调用SKSwizzle.SwapRedBlue交换 R/B 通道以匹配 GTK 的字节序。本版本对该类型有一处破坏性变更见 1.68.2 breaking diff移除了面向 Tizen 的重载LoadImageAsync(Xamarin.Forms.Platform.Tizen.Native.Image image, Xamarin.Forms.ImageSource imageSource, System.Threading.CancellationToken cancelationToken)Tizen 调用方需迁移到上述统一签名。而到 1.68.2.1 的 GTK diff 为止GTK 变体已无进一步 API 变化No changes。类型转换扩展Extensions 静态类public static class Extensions { // Xamarin.Forms ← SkiaSharp public static Xamarin.Forms.Color ToFormsColor (this SkiaSharp.SKColor color); public static Xamarin.Forms.Point ToFormsPoint (this SkiaSharp.SKPoint point); public static Xamarin.Forms.Point ToFormsPoint (this SkiaSharp.SKPointI point); public static Xamarin.Forms.Rectangle ToFormsRect (this SkiaSharp.SKRect rect); public static Xamarin.Forms.Rectangle ToFormsRect (this SkiaSharp.SKRectI rect); public static Xamarin.Forms.Size ToFormsSize (this SkiaSharp.SKSize size); public static Xamarin.Forms.Size ToFormsSize (this SkiaSharp.SKSizeI size); // SkiaSharp ← Xamarin.Forms public static SkiaSharp.SKColor ToSKColor (this Xamarin.Forms.Color color); public static SkiaSharp.SKPoint ToSKPoint (this Xamarin.Forms.Point point); public static SkiaSharp.SKRect ToSKRect (this Xamarin.Forms.Rectangle rect); public static SkiaSharp.SKSize ToSKSize (this Xamarin.Forms.Size size); }Extensions提供 SkiaSharp 基础几何/颜色类型与 Xamarin.Forms 对应类型之间的双向转换覆盖SKColor ↔ Color、SKPoint/SKPointI ↔ Point、SKRect/SKRectI ↔ Rectangle、SKSize/SKSizeI ↔ Size共 11 个扩展方法。这组方法常用于把SKCanvasView.CanvasSize或触摸坐标转成 Xamarin.Forms 布局/手势系统的类型。其设计模式与 GTK 侧 GTKExtensions.cs 中SKPointI ↔ Gdk.Point、SKRectI ↔ Gdk.Rectangle、SKColor ↔ Gdk.Color使用常量ColorMultiplier 65535f / 255f处理 16 位色深的扩展一一对应可见 SkiaSharp 各平台绑定均遵循扩展方法做类型互转的同一套架构约定。渲染器SKCanvasViewRenderer 与渲染基类GTK 后端的桥接由两个渲染器类型完成它们把 Xamarin.Forms 视图映射到 GTK 原生控件public class SKCanvasViewRenderer : SKCanvasViewRendererBaseSKCanvasView, SkiaSharp.Views.Gtk.SKWidget, Atk.Implementor, GLib.IWrapper, System.Collections.IEnumerable, System.IDisposable, Xamarin.Forms.IEffectControlProvider, Xamarin.Forms.IRegisterable, Xamarin.Forms.Platform.GTK.IVisualElementRenderer, Xamarin.Forms.Platform.GTK.IVisualNativeElementRenderer { public SKCanvasViewRenderer (); } public abstract class SKCanvasViewRendererBaseTFormsView, TNativeView : Xamarin.Forms.Platform.GTK.ViewRendererTFormsView, TNativeView, /* ...同上接口列表... */ { protected SKCanvasViewRendererBase (); protected virtual TNativeView CreateNativeControl (); protected override void Dispose (bool disposing); protected override void OnElementChanged (Xamarin.Forms.Platform.GTK.ElementChangedEventArgsTFormsView e); protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e); }泛型基类SKCanvasViewRendererBaseTFormsView, TNativeView继承自 Xamarin.Forms 的 GTKViewRendererTFormsView, TNativeView在 1.68.2 中实例化为SKCanvasViewRenderer : SKCanvasViewRendererBaseSKCanvasView, SkiaSharp.Views.Gtk.SKWidget即用 GTK 的SKWidget承载SKCanvasView生命周期钩子OnElementChanged在 Forms 元素挂接时创建原生控件CreateNativeControl并订阅事件OnElementPropertyChanged负责把EnableTouchEvents、IgnorePixelScaling等绑定属性的变化同步到原生层Dispose负责释放原生资源——1.68.2 专门修复了视图生命周期与释放问题发布说明 PR #1180、#1135、#1133强调在视图卸载时正确释放 Skia 对象。需要说明的是GTK 端真正的绘制宿主是仓库 SkiaSharp.Views.Gtk3 的 SKDrawingArea它在OnDrawn中按分配尺寸创建SKImageInfoSKImageInfo.PlatformColorTypePremulalpha通过SKSurface.Create(imgInfo, pix.DataPtr, imgInfo.RowBytes)把 CairoImageSurface的像素指针直接包装为 SkiaSKSurface绘制完成后Flush并以SKSwizzle.SwapRedBlue修正通道顺序再交给 Cairo 呈现。这从源码层面印证了SKCanvasView在 GTK 桌面端Forms 视图 → SKWidget → SKDrawingArea/Cairo 像素共享的完整链路。版本对照与迁移提示1.68.2本文基线SkiaSharp.Views.Forms含 GTK、WPF 变体命名空间整体新建程序集版本 1.68.0.0GTK 后端首次随 1.68.2 发布说明 提供SKImageSourceHandler移除 Tizen 专属重载breaking。1.68.2.1GTK 变体 无 API 变化。后续演进从仓库 releases 目录结构看SkiaSharp.Views.Forms及 GTK/WPF 变体在 2.80.x、2.88.x 系列仍持续发布而在当前仓库的 包文档 packages.md 中Xamarin.Forms 时代的SkiaSharp.Views.Forms系已被 .NET MAUI 的SkiaSharp.Views.Maui.Controls提供SKCanvasView/SKGLViewnet8.0与各平台原生包如 GTK3 的SKDrawingArea取代。若在全新项目中使用 SkiaSharp 的跨平台视图能力建议直接采用 MAUI/Uno 控件若维护 1.68.x 时代的 Xamarin.Forms 项目本文的 API 签名即为可依赖的权威依据。延伸阅读本文主文档1.68.2 SkiaSharp.Views.FormsGTKAPI diff同版本整体变更1.68.2 发布说明 与 API 变更索引破坏性变更明细1.68.2 breaking diff事件参数共享源码SKPaintSurfaceEventArgs.cs、SKPaintGLSurfaceEventArgs.csGTK 原生实现SKDrawingArea.cs、GTKExtensions.cs包体系与迁移映射packages.md赞分享图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载相关推荐SkiaSharp 1.68.2 版本变更深度解析Xamarin.Forms 的 SKGLView 控制器接口与触摸压感Pressure支持SkiaSharp 1.68.2 版本变更深度解析Xamarin.Forms 的 SKGLView 控制器接口与触摸压感Pressure支持 本篇技术指南图形学图像处理跨平台SkiaSharp.Views.Forms API 详解在 Xamarin.Forms 中集成 SKCanvasView 与 SKGLView 绘制 2D 图形SkiaSharp.Views.Forms API 详解在 Xamarin.Forms 中集成 SKCanvasView 与 SKGLView 绘制 2D 图图形学图像处理跨平台SkiaSharp 手指绘画实战用 SKPath 与 SKCanvasView 触摸事件打造多点触控绘图应用SkiaSharp 手指绘画实战用 SKPath 与 SKCanvasView 触摸事件打造多点触控绘图应用 本文以 .NET MAUI 应用为场景讲解如何图形学图像处理跨平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考