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

如何在Xamarin Forms中使用SkiaSharp在Canvas上绘制PDF?

如何在Xamarin Forms中使用SkiaSharp在Canvas上绘制PDF?

嘿,刚好我之前在项目里实现过类似的功能,给你一步步说清楚怎么操作,很容易上手的:

1. 安装必要的NuGet包

首先得把SkiaSharp相关的包装上,这是基础:

  • SkiaSharp:核心绘图库
  • SkiaSharp.Views.Forms:Xamarin Forms的视图绑定
  • SkiaSharp.Extended.Pdf:处理PDF的扩展包(这个很关键,原生SkiaSharp不直接支持PDF加载)

你可以通过NuGet包管理器搜索安装,或者用Package Manager控制台执行命令(版本选最新稳定版即可,注意三个包版本保持一致):

Install-Package SkiaSharp
Install-Package SkiaSharp.Views.Forms
Install-Package SkiaSharp.Extended.Pdf

2. 在XAML中添加SKCanvasView

在你的ContentPage里添加用于绘制的SKCanvasView,并绑定PaintSurface事件:

<?xml version="1.0" encoding="utf-8" ?>
<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="YourAppName.MainPage">
    <skia:SKCanvasView x:Name="PdfCanvasView" 
                       PaintSurface="OnPdfCanvasViewPaintSurface"/>
</ContentPage>

3. 加载PDF文档并处理资源

在页面的后台代码里,我们需要先加载PDF文件,同时要注意释放资源避免内存泄漏:

using SkiaSharp;
using SkiaSharp.Extended.Pdf;
using System.Reflection;
using Xamarin.Forms;

namespace YourAppName
{
    public partial class MainPage : ContentPage
    {
        private SKPdfDocument _pdfDocument;

        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            LoadPdfDocument();
        }

        protected override void OnDisappearing()
        {
            // 释放PDF资源,务必记得这一步
            _pdfDocument?.Dispose();
            _pdfDocument = null;
            base.OnDisappearing();
        }

        private void LoadPdfDocument()
        {
            // 这里以嵌入式PDF资源为例,你也可以换成本地文件路径、Assets等
            var assembly = typeof(MainPage).GetTypeInfo().Assembly;
            // 替换成你的项目中PDF资源的完整名称(项目名.文件夹.文件名.pdf)
            using var pdfStream = assembly.GetManifestResourceStream("YourAppName.Resources.Sample.pdf");
            
            if (pdfStream == null)
            {
                // 处理文件加载失败的情况,比如提示用户
                return;
            }

            _pdfDocument = SKPdfDocument.Load(pdfStream);
            // 触发画布重绘
            PdfCanvasView.InvalidateSurface();
        }
    }
}

4. 在PaintSurface事件中绘制PDF页面

最后一步就是把PDF页面画到Canvas上,我们可以做自适应缩放和居中处理:

private void OnPdfCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
    var surface = e.Surface;
    var canvas = surface.Canvas;
    // 清空画布为白色背景
    canvas.Clear(SKColors.White);

    // 如果PDF未加载完成,直接返回
    if (_pdfDocument == null || _pdfDocument.PageCount == 0)
    {
        return;
    }

    // 打开PDF的第一页(如果要显示多页,可以循环处理或者加分页逻辑)
    using var pdfPage = _pdfDocument.OpenPage(0);
    var pageSize = pdfPage.Size;
    var canvasSize = e.Info.Size;

    // 计算缩放比例,让页面完整适配画布
    var scaleFactor = Math.Min(canvasSize.Width / pageSize.Width, canvasSize.Height / pageSize.Height);
    // 计算偏移量,让页面在画布中居中
    var offsetX = (canvasSize.Width - pageSize.Width * scaleFactor) / 2;
    var offsetY = (canvasSize.Height - pageSize.Height * scaleFactor) / 2;

    // 平移和缩放画布
    canvas.Translate(offsetX, offsetY);
    canvas.Scale(scaleFactor);

    // 绘制PDF页面
    using var paint = new SKPaint();
    canvas.DrawPdfPage(pdfPage, paint);
}

一些额外的小提示

  • 资源路径注意:如果是Android的Assets文件夹,需要设置文件的Build Action为AndroidAsset,然后用AssetManager获取流;iOS则放在Resources文件夹,Build Action设为BundleResource。
  • 多页处理:如果PDF有多个页面,可以添加按钮切换页码,在绘制时打开对应索引的页面即可。
  • 内存管理:SKPdfDocument和SKPdfPage都是IDisposable类型,一定要记得Dispose,避免内存泄漏。

备注:内容来源于stack exchange,提问作者Hamza Oubouzid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 07:04:31