You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

问询Xamarin中基于SkiaSharp的跨平台触摸绘图解决方案

Cross-Platform Touch Drawing with SkiaSharp & TouchTracking in Xamarin.Forms

Great question! I’ve tackled this exact scenario before, and there’s a solid cross-platform solution using SkiaSharp and the official TouchTracking libraries that avoids the beta version headaches you mentioned. Here’s how to implement it properly:

Step 1: Install Stable NuGet Packages

Skip the outdated 0.1.0 beta versions—use these maintained, cross-platform packages:

  • SkiaSharp.Views.Forms: SkiaSharp’s official Xamarin.Forms integration for canvas rendering
  • TouchTracking.Forms: The stable, cross-platform touch event library (matches the core TouchTracking namespace)

Step 2: Replace BoxView with SKCanvasView

Instead of using a BoxView, use SKCanvasView directly—it’s optimized for SkiaSharp drawing and works seamlessly with touch tracking.

Step 3: Implement Touch Handling & Drawing

Here’s a complete working example:

XAML Layout

<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"
             xmlns:tt="clr-namespace:TouchTracking.Forms;assembly=TouchTracking.Forms"
             x:Class="DrawApp.MainPage">
    <skia:SKCanvasView x:Name="canvasView" BackgroundColor="White">
        <tt:TouchEffect.TouchActions>
            <tt:TouchActionEventHandler>
                <x:Arguments>
                    <x:String>OnCanvasTouch</x:String>
                </x:Arguments>
            </tt:TouchActionEventHandler>
        </tt:TouchEffect.TouchActions>
    </skia:SKCanvasView>
</ContentPage>

Code-Behind Logic

using SkiaSharp;
using SkiaSharp.Views.Forms;
using TouchTracking;
using Xamarin.Forms;

namespace DrawApp
{
    public partial class MainPage : ContentPage
    {
        private SKPath _currentDrawPath;
        private readonly List<SKPath> _savedPaths = new List<SKPath>();
        private readonly SKPaint _drawPaint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.DarkBlue,
            StrokeWidth = 6,
            StrokeCap = SKStrokeCap.Round, // Smooths line ends
            StrokeJoin = SKStrokeJoin.Round // Smooths line corners
        };

        public MainPage()
        {
            InitializeComponent();
            canvasView.PaintSurface += RenderCanvas;
        }

        private void OnCanvasTouch(object sender, TouchActionEventArgs args)
        {
            switch (args.Type)
            {
                case TouchActionType.Pressed:
                    // Start a new path when the user touches the screen
                    _currentDrawPath = new SKPath();
                    _currentDrawPath.MoveTo(args.Location);
                    break;
                case TouchActionType.Moved:
                    // Add to the path as the user drags their finger
                    _currentDrawPath?.LineTo(args.Location);
                    canvasView.InvalidateSurface(); // Trigger redraw
                    break;
                case TouchActionType.Released:
                    // Save the completed path and reset the current path
                    if (_currentDrawPath != null)
                    {
                        _savedPaths.Add(_currentDrawPath);
                        canvasView.InvalidateSurface();
                    }
                    _currentDrawPath = null;
                    break;
                case TouchActionType.Cancelled:
                    // Discard the current path if the touch is interrupted
                    _currentDrawPath = null;
                    break;
            }
        }

        private void RenderCanvas(object sender, SKPaintSurfaceEventArgs args)
        {
            var canvas = args.Surface.Canvas;
            canvas.Clear(SKColors.White); // Clear the canvas each frame

            // Draw all saved paths
            foreach (var path in _savedPaths)
            {
                canvas.DrawPath(path, _drawPaint);
            }

            // Draw the current in-progress path
            if (_currentDrawPath != null)
            {
                canvas.DrawPath(_currentDrawPath, _drawPaint);
            }
        }
    }
}

Key Advantages of This Approach

  • Fully Cross-Platform: Works on iOS, Android, and UWP without platform-specific code
  • Stable Libraries: No beta versions—both packages are actively maintained
  • Seamless Integration: TouchTracking.Forms uses the same core TouchTracking namespace and plays nicely with SkiaSharp’s canvas system
  • Extensible: Add features like color pickers, stroke width adjustment, or save/load functionality by modifying the SKPaint settings or _savedPaths collection

内容的提问来源于stack exchange,提问作者Kyoshiro Kokujou Obscuritas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:07:54