hi I need to make my widgets as a pdf file but I have a problems with it
when i try to convert it to the pdf file it doesn't works and show this error message
Error: Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/html/scene_builder.dart:94:16
matrix4[0] == window.devicePixelRatio &&
matrix4[5] == window.devicePixelRatio
is not true
error doesn't appear when i render with an canvaskit but if i render with canvasKit images our making problem...
does any one knows how to solve this problem??
here is the code
void printScreen() {
Printing.layoutPdf(
onLayout: (PdfPageFormat format) async {
final doc = pw.Document();
final image = await WidgetWraper.fromKey(
key: reportsKey,
pixelRatio: 3.0,
);
doc.addPage(
pw.Page(
pageFormat: format,
build: (pw.Context context) {
return pw.Center(
child: pw.Expanded(
child: pw.Image(image),
),
);
},
),
);
return doc.save();
},
);
}
Related
I use the pdf library and MultiPage, and I want to repeat the specific widget so that each widget is on a separate page. How do I do that?
I don't want to use addPage because I have a header, footer and some formats don't want to repeat it in every add page.
How can I add a new page to a MultiPage that already has the same formats?
// Create a PDF document.
final doc = pw.Document();
_logo = await rootBundle.loadString('assets/logo.svg');
_bgShape = await rootBundle.loadString('assets/invoice.svg');
=====> first_ Add page to the PDF <=======
doc.addPage(
pw.MultiPage(
pageTheme: _buildTheme(
pageFormat,
await PdfGoogleFonts.robotoRegular(),
await PdfGoogleFonts.robotoBold(),
await PdfGoogleFonts.robotoItalic(),
),
header: _buildHeader,
footer: _buildFooter,
build: (context) => [
//Insert to widget
],
),
);
======> second_ Add page to the PDF <========
doc.addPage(
pw.MultiPage(
pageTheme: _buildTheme(
pageFormat,
await PdfGoogleFonts.robotoRegular(),
await PdfGoogleFonts.robotoBold(),
await PdfGoogleFonts.robotoItalic(),
),
header: _buildHeader,
footer: _buildFooter,
build: (context) => [
//Insert to widget
],
),
);
// Return the PDF file content
return doc.save();
I try to read barcode using flutter mobile, I using this function
scanbarcode() async {
await FlutterBarcodeScanner.scanBarcode(
'#000000', 'Cancel', true, ScanMode.BARCODE)
.then((value) => setState(() => text = value));
}
it open camera and show scan line but it doesn't get the result it text, and when I press back or cancel it get me -1 in txt.
and that when I call
onPressed: () async {
await scanbarcode();
}
thanks
I know that on emultated phones bar and Qr code scanner do not work well so try to run your app on a real device. Otherwise I cannot help you more with your problem but I implemented a bar/QR code scanner few day ago with the qr_code_scanner: ^1.0.0 package and it worked for me.
Hier is the link of the package: https://pub.dev/packages/qr_code_scanner
and here the code exemple:
#override
Widget build(BuildContext context) {
final qrKey = GlobalKey(debugLabel: 'QR');
QRViewController? controller;
void onQRViewCreated(QRViewController controllerAt) {
controller = controllerAt;
controllerAt.pauseCamera();
controller!.resumeCamera();
controller!.scannedDataStream.listen((barcode) {
// Hier you get the barcode or qr code if it's scanned
});
}
Widget _getBarQrScannerWidget() {
return QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(
cutOutSize: MediaQuery.of(context).size.width * 0.75,
borderWidth: 10,
borderLength: 15,
borderRadius: 8,
),
);
}
return getBarQrScannerWidget()
}
We want to show image on a pdf from assets folder in Flutter web application:
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:flutter/material.dart';
.............
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
height: 400,
width: 900,
child: PdfPreview(
build: (format) => _generatePdf(format, "SOME TITLE"),
)),
),
]));
}
Future<Uint8List> _generatePdf(PdfPageFormat format) async {
final pdf = pw.Document();
pdf.addPage(
pw.Page(
pageFormat: format,
build: (context) {
return pw.Image(AssetImage('assets/imglogo.png')); //This line gives the error
}));
return pdf.save();
}
This code gives error:
The argument type 'AssetImage' can't be assigned to the parameter type 'ImageProvider'
The documentation addresses only two cases To load an image from a file:(dart.io is not supported on the web), and To load an image from the network using the printing package:, which is not the case, so we tried the solutions provided here: 1,2, but each one gives a different exception.
Is there another approach to achieve this?
You can convert your ByteData directly to Uint8List as shown in the example code below. This can then be passed to the MemoryImage constructor:
Future<void> addPage(pw.Document pdf, String filename) async {
final imageByteData = await rootBundle.load('assets/$filename');
// Convert ByteData to Uint8List
final imageUint8List = imageByteData.buffer
.asUint8List(imageByteData.offsetInBytes, imageByteData.lengthInBytes);
final image = pw.MemoryImage(imageUint8List);
pdf.addPage(
pw.Page(
build: (pw.Context context) {
return pw.Center(
child: pw.Image(image),
); // Center
},
),
);
}
To achieve this you can get the asset image as a file, and then use this file in the PDF. If I take your code, we can add a function to get a File representation of your asset image :
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final file = File('${(await getTemporaryDirectory()).path}/$path');
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
To make it works, you need to add path_provider to your dependencies.
Then you can use this function in your pdf generation function :
final pdf = pw.Document();
final file = await getImageFileFromAssets(yourpath);
final image = pw.MemoryImage(
file.readAsBytesSync(),
);
pdf.addPage(pw.Page(
pageFormat: format,
build: (context) {
return pw.Image(image);
}));
return pdf.save();
I am trying to simple generate and save pdf issue is its showing error in my code
I am doing like this
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
onTap: () async{
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Center(
child: pw.Text('Hello World!'),
),
),
);
// Share.shareFiles([pdf], text: 'Reports');
final output = await getTemporaryDirectory();
final path = "${output.path}/temp.pdf";
final file = File(path); // here its showing error 2 positional
await file.writeAsBytes(pdf.save()); // here its showing The method 'writeAsBytes' isn't defined for the type 'File'.
},
Plugin versions
pdf: 2.1.0 & path_provider: ^2.0.2
I search every where but I didnt find any solution cant find it so why I am getting this error -_-
Use io library to write the file:
import 'dart:io' as io;
onTap: () async{
final pdf = pw.Document();
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Center(
child: pw.Text('Hello World!'),
),
),
);
// Share.shareFiles([pdf], text: 'Reports');
//replace your code to save file from bellow
final output = await getTemporaryDirectory();
final path = "${output.path}/temp.pdf";
final file = await io.File(path).writeAsBytes(pdf.save());
},
The error would be due to methods defined in the pdf library. You can use default io library to solve that.
I'm in the process of Web'ifing a Flutter mobile application and attempting to get around the lack for support for Path Provider in Web.
I'm using the PDF (pdf: ^1.9.0) package to generate a PDF document and upload it to Google Drive and I'm trying to find out if I can generate and store the PDF In memory to make it web compatible.
Example current code using Path Provider.
createFile() async {
final downloads = await getApplicationSupportDirectory();
final file = File("${downloads.path}/$filename.pdf");
await file.writeAsBytes(pdf.save());
await GoogleDriveController.uploadFileToGoogleDrive(file.path);
}
Question: Is there a way to generate and store Fies in memory for web using Flutter web?
I managed to find a work around to generate the PDF and trigger a download via the browser instead and thought I should post incase anyone stumbles across this.
//Create PDF in Bytes
Uint8List pdfInBytes = pdf.save();
//Create blob and link from bytes
final blob = html.Blob([pdfInBytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'pdf.pdf';
html.document.body.children.add(anchor);
//Trigger the download of this PDF in the browser.
RaisedButton(
child: Text('Press'),
onPressed: () {
anchor.click();
Navigator.pop(context);
},
)
My answer is a variant on Yonkee above specifically for flutter web. In this answer, I have added the imports required (dart:html and dart:typed_data) and added formatting of text as I needed that feature.
import 'package:flutter/material.dart';
import 'package:pdf/widgets.dart' as pw;
import 'dart:typed_data';
import 'dart:html' as html;
class PDFSave extends StatefulWidget {
#override
_PDFSaveState createState() => _PDFSaveState();
}
class _PDFSaveState extends State<PDFSave> {
final pdf = pw.Document();
var anchor;
savePDF() async {
Uint8List pdfInBytes = await pdf.save();
final blob = html.Blob([pdfInBytes], 'application/pdf');
final url = html.Url.createObjectUrlFromBlob(blob);
anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'pdf.pdf';
html.document.body.children.add(anchor);
}
createPDF() async {
pdf.addPage(
pw.Page(
build: (pw.Context context) => pw.Column(
children: [
pw.Text('Hello World', style: pw.TextStyle(fontSize: 40)),
],
),
),
);
savePDF();
}
#override
void initState() {
super.initState();
createPDF();
}
#override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('PDF Creator'),
),
body: Center(
child:RaisedButton(
child: Text('Press'),
onPressed: () {
anchor.click();
Navigator.pop(context);
},
)
));
}
}