【问题标题】:Xamarin Android print PDF fileXamarin Android 打印 PDF 文件
【发布时间】:2017-08-05 18:54:50
【问题描述】:

我正在尝试打印使用 PrintManager 创建的 PDF 文件。我已经编写了代码以在我的活动中使用 ITextSharp 生成 PDF 文件。下面是我生成PDF的方法:

    private byte[] generatePdf()
    {
        using (var baos = new MemoryStream())
        {
            using (var ps = new StreamWriter(baos))
            {
                Document doc = new Document(PageSize.A4, 72, 72, 72, 72);
                PdfWriter writer = PdfWriter.GetInstance(doc, ps.BaseStream);
                if (!doc.IsOpen())
                    doc.Open();

                doc.AddTitle("Sales Order " + GlobalVars.selectedSales.DocumentNo);
                var TitleFont = new Font(Font.FontFamily.TIMES_ROMAN, 24, Font.BOLD);
                var SubTitleFont = new Font(Font.FontFamily.TIMES_ROMAN, 20);
                var HeadingFont = new Font(Font.FontFamily.TIMES_ROMAN, 18, Font.BOLD);
                var BoldNormalFont = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.BOLD);
                var NormalFont = new Font(Font.FontFamily.TIMES_ROMAN, 14);

                doc.Add(new Paragraph("SALES ORDER", TitleFont));
                ... //other data
                doc.Close();
                writer.Close();
            }
            var bytes = baos.ToArray();
            return bytes;
        }
    }

简而言之,上面的代码将返回包含生成的 PDF 文件的字节数组,因为我不想将 PDF 保存在 Android 设备中的任何位置。

生成此 PDF 后,我无法使用 PrintManager,它只需要 PrintDocumentAdapter 参数来生成文件,而不是使用我生成的 PDF。我正在尝试生成从PrintDocumentAdapter 继承的CustomPrintAdapter,但不知道如何重用我从我的活动中创建的PDF,因为它使用PrintedPdfDocument 数据类型。

你们能给我指出正确的方向吗?或者有没有其他更简单的方法来实现打印自定义 PDF 文件?

更新 1

根据这篇文章,Xamarin Android 不支持 System.Drawing.dll。我认为 ITextSharp 库使用 System.Drawing 库,因为当我尝试构建它时,它会引发异常:

Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. 
Perhaps it doesn't exist in the Mono for Android profile?

当我删除它时,构建成功并且没有引发异常。请注意,我已尝试关闭解决方案,从 Packages 文件夹中删除所有内容,重新打开解决方案并构建;在这种情况下它不起作用。

因此,我将尝试使用 Android 开发者网站上的Android.Graphics.Canvas 生成 PDF。

【问题讨论】:

    标签: c# android pdf xamarin printing


    【解决方案1】:

    更新 2

    我没有像Android developer site 那样使用Android.Graphics.Canvas 成功生成PDF。原因是我不知道如何计算页面并更改页面,因为内容是动态的。网站上还有一个类似getPrintItemCount()的方法,我不知道那是什么,因为该网站不包括那里的解释。

    因此,我现在能想到的解决方法是打印由我的 Web 服务端点处理的 WebView。我正在为要打印的页面创建 HTML 布局,然后 WebView 将打开我的 Web 服务端点。幸运的是,用这种方法打印可以做得很好。当然,这种方法也有局限性,即 Web 服务应该可以访问以进行打印。

    为此,首先,我需要创建一个扩展WebViewClient 的自定义类,以便在使用OnPageFinished 方法完成页面加载时获取事件。然后,我使用我的活动中的打印方法,我使用构造函数传递它。为了更清楚,我将附上我的代码。

    public class CustomWebViewClient : WebViewClient
    {
        private SalesDetailView myActivity;
        public bool shouldOverrideUrlLoading(WebView view, string url)
        {
            return false;
        }
        public override void OnPageFinished(WebView view, string url)
        {
            Log.Debug("PRINT", "page finished loading " + url);
            myActivity.doWebViewPrint(url);
            base.OnPageFinished(view, url);
        }
        public CustomWebViewClient(SalesDetailView activity)
        {
            myActivity = activity;
        }
    }
    

    这是我活动中的 doWebPrint 方法

    public async void doWebViewPrint(string URL)
        {
            if (await vm.printCheck())
            {
                PrintDocumentAdapter adapter;
                if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
                    adapter = webView.CreatePrintDocumentAdapter("test");
                else
                    adapter = webView.CreatePrintDocumentAdapter();
                var printMgr = (PrintManager)GetSystemService(PrintService);
                printMgr.Print("printTest", adapter, null);
            }
        }
    

    然后我创建WebView,在用户点击打印按钮时加载网站。

    Button btnPrintSO = FindViewById<Button>(Resource.Id.btnPrintSO);
    btnPrintSO.Click += delegate
    {
        string URL = ServerDatabaseApi.printSOEndpoint + GlobalVars.selectedSales.DocumentNo;
        webView = new WebView(this);
        CustomWebViewClient client = new CustomWebViewClient(this);
        webView.SetWebViewClient(client);
        webView.Settings.JavaScriptEnabled = true;
        webView.LoadUrl(URL);
        webView.Settings.UseWideViewPort = true;
        webView.Settings.LoadWithOverviewMode = true;
    };
    

    希望这些更新能在未来对任何人有所帮助。

    【讨论】:

    • 你可以在本地构建 html,不是吗?
    • @VassilisGr 你的意思是在 Android 上?是的,当然可以。我更喜欢在服务器上构建 html,以便 Android 接收最终数据 (html),这意味着 Android 可以立即使用数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2016-05-21
    • 2016-01-10
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多