Showing
10 changed files
with
379 additions
and
3 deletions
@@ -28,6 +28,7 @@ printing/android/local.properties | @@ -28,6 +28,7 @@ printing/android/local.properties | ||
28 | printing/*.log | 28 | printing/*.log |
29 | printing/ios/Flutter | 29 | printing/ios/Flutter |
30 | printing/ios/Runner | 30 | printing/ios/Runner |
31 | +printing/android/.gradle | ||
31 | 32 | ||
32 | .pana | 33 | .pana |
33 | pedantic_analyis_options_*.yaml | 34 | pedantic_analyis_options_*.yaml |
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package android.print; | ||
18 | + | ||
19 | +import android.app.Activity; | ||
20 | +import android.os.CancellationSignal; | ||
21 | +import android.os.ParcelFileDescriptor; | ||
22 | + | ||
23 | +import java.io.File; | ||
24 | +import java.io.FileInputStream; | ||
25 | +import java.io.FileNotFoundException; | ||
26 | +import java.io.IOException; | ||
27 | +import java.io.InputStream; | ||
28 | + | ||
29 | +public class PdfConvert { | ||
30 | + public static void print(final Activity activity, final PrintDocumentAdapter adapter, | ||
31 | + final PrintAttributes attributes, final Result result) { | ||
32 | + adapter.onLayout(null, attributes, null, new PrintDocumentAdapter.LayoutResultCallback() { | ||
33 | + @Override | ||
34 | + public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { | ||
35 | + File outputDir = activity.getCacheDir(); | ||
36 | + File outputFile = null; | ||
37 | + try { | ||
38 | + outputFile = File.createTempFile("printing", "pdf", outputDir); | ||
39 | + } catch (IOException e) { | ||
40 | + outputFile.delete(); | ||
41 | + result.onError(e.getMessage()); | ||
42 | + return; | ||
43 | + } | ||
44 | + | ||
45 | + try { | ||
46 | + final File finalOutputFile = outputFile; | ||
47 | + adapter.onWrite(new PageRange[] {PageRange.ALL_PAGES}, | ||
48 | + ParcelFileDescriptor.open( | ||
49 | + outputFile, ParcelFileDescriptor.MODE_READ_WRITE), | ||
50 | + new CancellationSignal(), | ||
51 | + new PrintDocumentAdapter.WriteResultCallback() { | ||
52 | + @Override | ||
53 | + public void onWriteFinished(PageRange[] pages) { | ||
54 | + super.onWriteFinished(pages); | ||
55 | + | ||
56 | + if (pages.length == 0) { | ||
57 | + finalOutputFile.delete(); | ||
58 | + result.onError("No page created"); | ||
59 | + } | ||
60 | + | ||
61 | + result.onSuccess(finalOutputFile); | ||
62 | + finalOutputFile.delete(); | ||
63 | + } | ||
64 | + }); | ||
65 | + } catch (FileNotFoundException e) { | ||
66 | + outputFile.delete(); | ||
67 | + result.onError(e.getMessage()); | ||
68 | + } | ||
69 | + } | ||
70 | + }, null); | ||
71 | + } | ||
72 | + | ||
73 | + public static byte[] readFile(File file) throws IOException { | ||
74 | + byte[] buffer = new byte[(int) file.length()]; | ||
75 | + InputStream ios = null; | ||
76 | + try { | ||
77 | + ios = new FileInputStream(file); | ||
78 | + if (ios.read(buffer) == -1) { | ||
79 | + throw new IOException("EOF reached while trying to read the whole file"); | ||
80 | + } | ||
81 | + } finally { | ||
82 | + try { | ||
83 | + if (ios != null) ios.close(); | ||
84 | + } catch (IOException e) { | ||
85 | + } | ||
86 | + } | ||
87 | + return buffer; | ||
88 | + } | ||
89 | + | ||
90 | + public interface Result { | ||
91 | + void onSuccess(File file); | ||
92 | + | ||
93 | + void onError(String message); | ||
94 | + } | ||
95 | +} |
@@ -16,22 +16,24 @@ | @@ -16,22 +16,24 @@ | ||
16 | 16 | ||
17 | package net.nfet.flutter.printing; | 17 | package net.nfet.flutter.printing; |
18 | 18 | ||
19 | -import static java.lang.StrictMath.max; | ||
20 | - | ||
21 | import android.app.Activity; | 19 | import android.app.Activity; |
22 | import android.content.Context; | 20 | import android.content.Context; |
23 | import android.content.Intent; | 21 | import android.content.Intent; |
24 | import android.net.Uri; | 22 | import android.net.Uri; |
23 | +import android.os.Build; | ||
25 | import android.os.Bundle; | 24 | import android.os.Bundle; |
26 | import android.os.CancellationSignal; | 25 | import android.os.CancellationSignal; |
27 | import android.os.Environment; | 26 | import android.os.Environment; |
28 | import android.os.ParcelFileDescriptor; | 27 | import android.os.ParcelFileDescriptor; |
29 | import android.print.PageRange; | 28 | import android.print.PageRange; |
29 | +import android.print.PdfConvert; | ||
30 | import android.print.PrintAttributes; | 30 | import android.print.PrintAttributes; |
31 | import android.print.PrintDocumentAdapter; | 31 | import android.print.PrintDocumentAdapter; |
32 | import android.print.PrintDocumentInfo; | 32 | import android.print.PrintDocumentInfo; |
33 | import android.print.PrintManager; | 33 | import android.print.PrintManager; |
34 | import android.print.pdf.PrintedPdfDocument; | 34 | import android.print.pdf.PrintedPdfDocument; |
35 | +import android.webkit.WebView; | ||
36 | +import android.webkit.WebViewClient; | ||
35 | import androidx.core.content.FileProvider; | 37 | import androidx.core.content.FileProvider; |
36 | 38 | ||
37 | import java.io.File; | 39 | import java.io.File; |
@@ -155,6 +157,28 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | @@ -155,6 +157,28 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | ||
155 | sharePdf((byte[]) call.argument("doc"), (String) call.argument("name")); | 157 | sharePdf((byte[]) call.argument("doc"), (String) call.argument("name")); |
156 | result.success(0); | 158 | result.success(0); |
157 | break; | 159 | break; |
160 | + case "convertHtml": | ||
161 | + double width = (double) call.argument("width"); | ||
162 | + double height = (double) call.argument("height"); | ||
163 | + double marginLeft = (double) call.argument("marginLeft"); | ||
164 | + double marginTop = (double) call.argument("marginTop"); | ||
165 | + double marginRight = (double) call.argument("marginRight"); | ||
166 | + double marginBottom = (double) call.argument("marginBottom"); | ||
167 | + | ||
168 | + PrintAttributes.Margins margins = | ||
169 | + new PrintAttributes.Margins(Double.valueOf(marginLeft * 1000.0).intValue(), | ||
170 | + Double.valueOf(marginTop * 1000.0 / 72.0).intValue(), | ||
171 | + Double.valueOf(marginRight * 1000.0 / 72.0).intValue(), | ||
172 | + Double.valueOf(marginBottom * 1000.0 / 72.0).intValue()); | ||
173 | + | ||
174 | + PrintAttributes.MediaSize size = new PrintAttributes.MediaSize("flutter_printing", | ||
175 | + "Provided size", Double.valueOf(width * 1000.0 / 72.0).intValue(), | ||
176 | + Double.valueOf(height * 1000.0 / 72.0).intValue()); | ||
177 | + | ||
178 | + convertHtml((String) call.argument("html"), size, margins, | ||
179 | + (String) call.argument("baseUrl")); | ||
180 | + result.success(0); | ||
181 | + break; | ||
158 | default: | 182 | default: |
159 | result.notImplemented(); | 183 | result.notImplemented(); |
160 | break; | 184 | break; |
@@ -192,4 +216,49 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | @@ -192,4 +216,49 @@ public class PrintingPlugin extends PrintDocumentAdapter implements MethodCallHa | ||
192 | e.printStackTrace(); | 216 | e.printStackTrace(); |
193 | } | 217 | } |
194 | } | 218 | } |
219 | + | ||
220 | + private void convertHtml(String data, final PrintAttributes.MediaSize size, | ||
221 | + final PrintAttributes.Margins margins, String baseUrl) { | ||
222 | + final WebView webView = new WebView(activity.getApplicationContext()); | ||
223 | + | ||
224 | + webView.loadDataWithBaseURL(baseUrl, data, "text/HTML", "UTF-8", null); | ||
225 | + | ||
226 | + webView.setWebViewClient(new WebViewClient() { | ||
227 | + @Override | ||
228 | + public void onPageFinished(WebView view, String url) { | ||
229 | + super.onPageFinished(view, url); | ||
230 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||
231 | + PrintAttributes attributes = | ||
232 | + new PrintAttributes.Builder() | ||
233 | + .setMediaSize(size) | ||
234 | + .setResolution( | ||
235 | + new PrintAttributes.Resolution("pdf", "pdf", 600, 600)) | ||
236 | + .setMinMargins(margins) | ||
237 | + .build(); | ||
238 | + | ||
239 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
240 | + final PrintDocumentAdapter adapter = | ||
241 | + webView.createPrintDocumentAdapter("printing"); | ||
242 | + | ||
243 | + PdfConvert.print(activity, adapter, attributes, new PdfConvert.Result() { | ||
244 | + @Override | ||
245 | + public void onSuccess(File file) { | ||
246 | + try { | ||
247 | + byte[] fileContent = PdfConvert.readFile(file); | ||
248 | + channel.invokeMethod("onHtmlRendered", fileContent); | ||
249 | + } catch (IOException e) { | ||
250 | + onError(e.getMessage()); | ||
251 | + } | ||
252 | + } | ||
253 | + | ||
254 | + @Override | ||
255 | + public void onError(String message) { | ||
256 | + channel.invokeMethod("onHtmlError", message); | ||
257 | + } | ||
258 | + }); | ||
259 | + } | ||
260 | + } | ||
261 | + } | ||
262 | + }); | ||
263 | + } | ||
195 | } | 264 | } |
printing/example/assets/example.html
0 → 100644
1 | +<!DOCTYPE html> | ||
2 | +<html> | ||
3 | + | ||
4 | +<head> | ||
5 | + <style> | ||
6 | + * { | ||
7 | + font-family: Arial, Helvetica, sans-serif; | ||
8 | + } | ||
9 | + | ||
10 | + table, | ||
11 | + th, | ||
12 | + td { | ||
13 | + border: 1px solid black; | ||
14 | + border-collapse: collapse; | ||
15 | + } | ||
16 | + | ||
17 | + th, | ||
18 | + td { | ||
19 | + padding: 5px; | ||
20 | + } | ||
21 | + </style> | ||
22 | +</head> | ||
23 | + | ||
24 | +<body> | ||
25 | + <h2>Html conversion</h2> | ||
26 | + | ||
27 | + <caption>Sample HTML Table</caption> | ||
28 | + <table> | ||
29 | + <tr> | ||
30 | + <th>Company</th> | ||
31 | + <th>Contact</th> | ||
32 | + <th>Country</th> | ||
33 | + </tr> | ||
34 | + <tr> | ||
35 | + <td>Alfreds Futterkiste</td> | ||
36 | + <td>Maria Anders</td> | ||
37 | + <td>Germany</td> | ||
38 | + </tr> | ||
39 | + <tr> | ||
40 | + <td>Centro comercial Moctezuma</td> | ||
41 | + <td>Francisco Chang</td> | ||
42 | + <td>Mexico</td> | ||
43 | + </tr> | ||
44 | + <tr> | ||
45 | + <td>Ernst Handel</td> | ||
46 | + <td>Roland Mendel</td> | ||
47 | + <td>Austria</td> | ||
48 | + </tr> | ||
49 | + <tr> | ||
50 | + <td>Island Trading</td> | ||
51 | + <td>Helen Bennett</td> | ||
52 | + <td>UK</td> | ||
53 | + </tr> | ||
54 | + <tr> | ||
55 | + <td>Laughing Bacchus Winecellars</td> | ||
56 | + <td>Yoshi Tannamuri</td> | ||
57 | + <td>Canada</td> | ||
58 | + </tr> | ||
59 | + <tr> | ||
60 | + <td>Magazzini Alimentari Riuniti</td> | ||
61 | + <td>Giovanni Rovelli</td> | ||
62 | + <td>Italy</td> | ||
63 | + </tr> | ||
64 | + </table> | ||
65 | + | ||
66 | + <p>HTML links are defined with the a tag:</p> | ||
67 | + | ||
68 | + <a href="https://github.com/DavBfr/dart_pdf">This is a link</a> | ||
69 | + | ||
70 | + <h2>An Unordered HTML List</h2> | ||
71 | + | ||
72 | + <ul> | ||
73 | + <li>Coffee</li> | ||
74 | + <li>Tea</li> | ||
75 | + <li>Milk</li> | ||
76 | + </ul> | ||
77 | + | ||
78 | + <h2>An Ordered HTML List</h2> | ||
79 | + | ||
80 | + <ol> | ||
81 | + <li>Coffee</li> | ||
82 | + <li>Tea</li> | ||
83 | + <li>Milk</li> | ||
84 | + </ol> | ||
85 | + | ||
86 | +</body> | ||
87 | + | ||
88 | +</html> |
@@ -5,6 +5,7 @@ import 'dart:ui' as ui; | @@ -5,6 +5,7 @@ import 'dart:ui' as ui; | ||
5 | 5 | ||
6 | import 'package:flutter/material.dart'; | 6 | import 'package:flutter/material.dart'; |
7 | import 'package:flutter/rendering.dart'; | 7 | import 'package:flutter/rendering.dart'; |
8 | +import 'package:flutter/services.dart'; | ||
8 | import 'package:path_provider/path_provider.dart'; | 9 | import 'package:path_provider/path_provider.dart'; |
9 | 10 | ||
10 | import 'package:pdf/pdf.dart'; | 11 | import 'package:pdf/pdf.dart'; |
@@ -94,6 +95,14 @@ class MyAppState extends State<MyApp> { | @@ -94,6 +95,14 @@ class MyAppState extends State<MyApp> { | ||
94 | }); | 95 | }); |
95 | } | 96 | } |
96 | 97 | ||
98 | + Future<void> _printHtml() async { | ||
99 | + print('Print html ...'); | ||
100 | + await Printing.layoutPdf(onLayout: (PdfPageFormat format) async { | ||
101 | + final String html = await rootBundle.loadString('assets/example.html'); | ||
102 | + return await Printing.convertHtml(format: format, html: html); | ||
103 | + }); | ||
104 | + } | ||
105 | + | ||
97 | @override | 106 | @override |
98 | Widget build(BuildContext context) { | 107 | Widget build(BuildContext context) { |
99 | return RepaintBoundary( | 108 | return RepaintBoundary( |
@@ -117,6 +126,8 @@ class MyAppState extends State<MyApp> { | @@ -117,6 +126,8 @@ class MyAppState extends State<MyApp> { | ||
117 | onPressed: _printScreen), | 126 | onPressed: _printScreen), |
118 | RaisedButton( | 127 | RaisedButton( |
119 | child: const Text('Save to file'), onPressed: _saveAsFile), | 128 | child: const Text('Save to file'), onPressed: _saveAsFile), |
129 | + RaisedButton( | ||
130 | + child: const Text('Print Html'), onPressed: _printHtml), | ||
120 | ], | 131 | ], |
121 | ), | 132 | ), |
122 | ), | 133 | ), |
@@ -16,10 +16,12 @@ | @@ -16,10 +16,12 @@ | ||
16 | 16 | ||
17 | import Flutter | 17 | import Flutter |
18 | import UIKit | 18 | import UIKit |
19 | +import WebKit | ||
19 | 20 | ||
20 | public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionControllerDelegate { | 21 | public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionControllerDelegate { |
21 | private var channel: FlutterMethodChannel? | 22 | private var channel: FlutterMethodChannel? |
22 | private var renderer: PdfPrintPageRenderer? | 23 | private var renderer: PdfPrintPageRenderer? |
24 | + private var urlObservation: NSKeyValueObservation? | ||
23 | 25 | ||
24 | init(_ channel: FlutterMethodChannel?) { | 26 | init(_ channel: FlutterMethodChannel?) { |
25 | super.init() | 27 | super.init() |
@@ -52,6 +54,30 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | @@ -52,6 +54,30 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | ||
52 | ) | 54 | ) |
53 | } | 55 | } |
54 | result(NSNumber(value: 1)) | 56 | result(NSNumber(value: 1)) |
57 | + } else if call.method == "convertHtml" { | ||
58 | + let width = CGFloat((args["width"] as? NSNumber)?.floatValue ?? 0.0) | ||
59 | + let height = CGFloat((args["height"] as? NSNumber)?.floatValue ?? 0.0) | ||
60 | + let marginLeft = CGFloat((args["marginLeft"] as? NSNumber)?.floatValue ?? 0.0) | ||
61 | + let marginTop = CGFloat((args["marginTop"] as? NSNumber)?.floatValue ?? 0.0) | ||
62 | + let marginRight = CGFloat((args["marginRight"] as? NSNumber)?.floatValue ?? 0.0) | ||
63 | + let marginBottom = CGFloat((args["marginBottom"] as? NSNumber)?.floatValue ?? 0.0) | ||
64 | + convertHtml( | ||
65 | + (args["html"] as? String)!, | ||
66 | + withPageSize: CGRect( | ||
67 | + x: 0.0, | ||
68 | + y: 0.0, | ||
69 | + width: width, | ||
70 | + height: height | ||
71 | + ), | ||
72 | + andMargin: CGRect( | ||
73 | + x: marginLeft, | ||
74 | + y: marginTop, | ||
75 | + width: width - marginRight - marginLeft, | ||
76 | + height: height - marginBottom - marginTop | ||
77 | + ), | ||
78 | + andBaseUrl: args["baseUrl"] as? String == nil ? nil : URL(string: (args["baseUrl"] as? String)!) | ||
79 | + ) | ||
80 | + result(NSNumber(value: 1)) | ||
55 | } else { | 81 | } else { |
56 | result(FlutterMethodNotImplemented) | 82 | result(FlutterMethodNotImplemented) |
57 | } | 83 | } |
@@ -118,4 +144,56 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | @@ -118,4 +144,56 @@ public class SwiftPrintingPlugin: NSObject, FlutterPlugin, UIPrintInteractionCon | ||
118 | } | 144 | } |
119 | UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true) | 145 | UIApplication.shared.keyWindow?.rootViewController?.present(activityViewController, animated: true) |
120 | } | 146 | } |
147 | + | ||
148 | + func convertHtml(_ data: String, withPageSize rect: CGRect, andMargin margin: CGRect, andBaseUrl baseUrl: URL?) { | ||
149 | + let viewController = UIApplication.shared.delegate?.window?!.rootViewController | ||
150 | + let wkWebView = WKWebView(frame: viewController!.view.bounds) | ||
151 | + wkWebView.isHidden = true | ||
152 | + wkWebView.tag = 100 | ||
153 | + viewController?.view.addSubview(wkWebView) | ||
154 | + wkWebView.loadHTMLString(data, baseURL: baseUrl ?? Bundle.main.bundleURL) | ||
155 | + | ||
156 | + urlObservation = wkWebView.observe(\.isLoading, changeHandler: { _, _ in | ||
157 | + // this is workaround for issue with loading local images | ||
158 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { | ||
159 | + // assign the print formatter to the print page renderer | ||
160 | + let renderer = UIPrintPageRenderer() | ||
161 | + renderer.addPrintFormatter(wkWebView.viewPrintFormatter(), startingAtPageAt: 0) | ||
162 | + | ||
163 | + // assign paperRect and printableRect values | ||
164 | + renderer.setValue(rect, forKey: "paperRect") | ||
165 | + renderer.setValue(margin, forKey: "printableRect") | ||
166 | + | ||
167 | + // create pdf context and draw each page | ||
168 | + let pdfData = NSMutableData() | ||
169 | + UIGraphicsBeginPDFContextToData(pdfData, .zero, nil) | ||
170 | + | ||
171 | + for i in 0 ..< renderer.numberOfPages { | ||
172 | + UIGraphicsBeginPDFPage() | ||
173 | + renderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds()) | ||
174 | + } | ||
175 | + | ||
176 | + UIGraphicsEndPDFContext() | ||
177 | + | ||
178 | + if let viewWithTag = viewController?.view.viewWithTag(wkWebView.tag) { | ||
179 | + viewWithTag.removeFromSuperview() // remove hidden webview when pdf is generated | ||
180 | + | ||
181 | + // clear WKWebView cache | ||
182 | + if #available(iOS 9.0, *) { | ||
183 | + WKWebsiteDataStore.default().fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in | ||
184 | + records.forEach { record in | ||
185 | + WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes, for: [record], completionHandler: {}) | ||
186 | + } | ||
187 | + } | ||
188 | + } | ||
189 | + } | ||
190 | + | ||
191 | + // dispose urlObservation | ||
192 | + self.urlObservation = nil | ||
193 | + | ||
194 | + let data = FlutterStandardTypedData(bytes: pdfData as Data) | ||
195 | + self.channel?.invokeMethod("onHtmlRendered", arguments: data) | ||
196 | + } | ||
197 | + }) | ||
198 | + } | ||
121 | } | 199 | } |
@@ -21,6 +21,7 @@ typedef LayoutCallback = FutureOr<List<int>> Function(PdfPageFormat format); | @@ -21,6 +21,7 @@ typedef LayoutCallback = FutureOr<List<int>> Function(PdfPageFormat format); | ||
21 | mixin Printing { | 21 | mixin Printing { |
22 | static const MethodChannel _channel = MethodChannel('printing'); | 22 | static const MethodChannel _channel = MethodChannel('printing'); |
23 | static LayoutCallback _onLayout; | 23 | static LayoutCallback _onLayout; |
24 | + static Completer<List<int>> _onHtmlRendered; | ||
24 | 25 | ||
25 | static Future<void> _handleMethod(MethodCall call) async { | 26 | static Future<void> _handleMethod(MethodCall call) async { |
26 | switch (call.method) { | 27 | switch (call.method) { |
@@ -37,6 +38,12 @@ mixin Printing { | @@ -37,6 +38,12 @@ mixin Printing { | ||
37 | 'doc': Uint8List.fromList(bytes), | 38 | 'doc': Uint8List.fromList(bytes), |
38 | }; | 39 | }; |
39 | return await _channel.invokeMethod('writePdf', params); | 40 | return await _channel.invokeMethod('writePdf', params); |
41 | + case 'onHtmlRendered': | ||
42 | + _onHtmlRendered.complete(call.arguments); | ||
43 | + break; | ||
44 | + case 'onHtmlError': | ||
45 | + _onHtmlRendered.completeError(call.arguments); | ||
46 | + break; | ||
40 | } | 47 | } |
41 | } | 48 | } |
42 | 49 | ||
@@ -89,4 +96,25 @@ mixin Printing { | @@ -89,4 +96,25 @@ mixin Printing { | ||
89 | }; | 96 | }; |
90 | return await _channel.invokeMethod('sharePdf', params); | 97 | return await _channel.invokeMethod('sharePdf', params); |
91 | } | 98 | } |
99 | + | ||
100 | + static Future<List<int>> convertHtml( | ||
101 | + {@required String html, | ||
102 | + String baseUrl, | ||
103 | + PdfPageFormat format = PdfPageFormat.a4}) async { | ||
104 | + final Map<String, dynamic> params = <String, dynamic>{ | ||
105 | + 'html': html, | ||
106 | + 'baseUrl': baseUrl, | ||
107 | + 'width': format.width, | ||
108 | + 'height': format.height, | ||
109 | + 'marginLeft': format.marginLeft, | ||
110 | + 'marginTop': format.marginTop, | ||
111 | + 'marginRight': format.marginRight, | ||
112 | + 'marginBottom': format.marginBottom, | ||
113 | + }; | ||
114 | + | ||
115 | + _channel.setMethodCallHandler(_handleMethod); | ||
116 | + _onHtmlRendered = Completer<List<int>>(); | ||
117 | + await _channel.invokeMethod<void>('convertHtml', params); | ||
118 | + return _onHtmlRendered.future; | ||
119 | + } | ||
92 | } | 120 | } |
@@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | @@ -4,7 +4,7 @@ description: Plugin that allows Flutter apps to generate and print documents to | ||
4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/printing |
5 | repository: https://github.com/DavBfr/dart_pdf | 5 | repository: https://github.com/DavBfr/dart_pdf |
6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
7 | -version: 2.0.4 | 7 | +version: 2.1.0 |
8 | 8 | ||
9 | environment: | 9 | environment: |
10 | sdk: ">=2.1.0 <3.0.0" | 10 | sdk: ">=2.1.0 <3.0.0" |
-
Please register or login to post a comment