A library that provides printing functionality for Android and iOS (AirPrint).
expo-print
provides an API for Android and iOS (AirPrint) printing functionality.
Android Device | Android Emulator | iOS Device | iOS Simulator | Web |
---|---|---|---|---|
-
npx expo install expo-print
If you're installing this in a bare React Native app, you should also follow these additional installation instructions.
import * as React from 'react';
import { View, StyleSheet, Button, Platform, Text } from 'react-native';
import * as Print from 'expo-print';
import { shareAsync } from 'expo-sharing';
const html = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
</head>
<body style="text-align: center;">
<h1 style="font-size: 50px; font-family: Helvetica Neue; font-weight: normal;">
Hello Expo!
</h1>
<img
src="https://d30j33t1r58ioz.cloudfront.net/static/guides/sdk.png"
style="width: 90vw;" />
</body>
</html>
`;
export default function App() {
const [selectedPrinter, setSelectedPrinter] = React.useState();
const print = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
await Print.printAsync({
html,
printerUrl: selectedPrinter?.url, // iOS only
});
};
const printToFile = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
const { uri } = await Print.printToFileAsync({ html });
console.log('File has been saved to:', uri);
await shareAsync(uri, { UTI: '.pdf', mimeType: 'application/pdf' });
};
const selectPrinter = async () => {
const printer = await Print.selectPrinterAsync(); // iOS only
setSelectedPrinter(printer);
};
return (
<View style={styles.container}>
<Button title="Print" onPress={print} />
<View style={styles.spacer} />
<Button title="Print to PDF file" onPress={printToFile} />
{Platform.OS === 'ios' && (
<>
<View style={styles.spacer} />
<Button title="Select printer" onPress={selectPrinter} />
<View style={styles.spacer} />
{selectedPrinter ? (
<Text style={styles.printer}>{`Selected printer: ${selectedPrinter.name}`}</Text>
) : undefined}
</>
)}
</View>
);
}
%%placeholder-start%%const styles = StyleSheet.create({ ... }); %%placeholder-end%%const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
flexDirection: 'column',
padding: 8,
},
spacer: {
height: 8,
},
printer: {
textAlign: 'center',
},
});
import * as Print from 'expo-print';
Print.printAsync(options)
Name | Type | Description |
---|---|---|
options | PrintOptions | A map defining what should be printed. |
Prints a document or HTML, on web this prints the HTML from the page.
Note: On iOS, printing from HTML source doesn't support local asset URLs (due to
WKWebView
limitations). As a workaround you can use inlined base64-encoded strings. See this comment for more details.
Returns
Promise<void>
Resolves to an empty Promise
if printing started.
Print.printToFileAsync(options)
Name | Type | Description |
---|---|---|
options (optional) | FilePrintOptions | A map of print options. Default: {} |
Prints HTML to PDF file and saves it to app's cache directory. On Web this method opens the print dialog.
Returns
Print.selectPrinterAsync()
Chooses a printer that can be later used in printAsync
Returns
A promise which fulfils with an object containing name
and url
of the selected printer.
OrientationType
The possible values of orientation for the printed content.
OrientationType Properties
Name | Type | Description |
---|---|---|
landscape | string | - |
portrait | string | - |
FilePrintOptions
Name | Type | Description |
---|---|---|
base64 (optional) | boolean | Whether to include base64 encoded string of the file in the returned object. |
height (optional) | number | Height of the single page in pixels. Defaults to |
html (optional) | string | HTML string to print into PDF file. |
margins (optional) | PageMargins | Only for: iOS Page margins for the printed document. |
useMarkupFormatter (optional) | boolean | Only for: iOS Alternative to default option that uses UIMarkupTextPrintFormatter instead of WebView, but it doesn't display images. |
width (optional) | number | Width of the single page in pixels. Defaults to |
FilePrintResult
Name | Type | Description |
---|---|---|
base64 (optional) | string | Base64 encoded string containing the data of the PDF file. Available only if |
numberOfPages | number | Number of pages that were needed to render given content. |
uri | string | A URI to the printed PDF file. |
PrintOptions
Name | Type | Description |
---|---|---|
height (optional) | number | Height of the single page in pixels. Defaults to |
html (optional) | string | Only for: Android iOS HTML string to print. |
margins (optional) | PageMargins | Only for: iOS Page margins for the printed document. |
markupFormatterIOS (optional) | string |
iOS |
orientation (optional) | OrientationType['portrait'] | OrientationType['landscape'] | Only for: iOS The orientation of the printed content, |
printerUrl (optional) | string | Only for: iOS URL of the printer to use. Returned from |
uri (optional) | string | Only for: iOS URI of a PDF file to print. Remote, local (ex. selected via |
useMarkupFormatter (optional) | boolean | Only for: iOS Alternative to default option that uses UIMarkupTextPrintFormatter instead of WebView, but it doesn't display images. |
width (optional) | number | Width of the single page in pixels. Defaults to |
Printer
Name | Type | Description |
---|---|---|
name | string | Name of the printer. |
url | string | URL of the printer. |
On iOS, printing from HTML source doesn't support local asset URLs (due to WKWebView limitations). Instead, images need to be converted to base64 and inlined into the HTML.
import { Asset } from 'expo-asset';
import { printAsync } from 'expo-print';
import { manipulateAsync } from 'expo-image-manipulator';
async function generateHTML() {
const asset = Asset.fromModule(require('../../assets/logo.png'));
const image = await manipulateAsync(asset.localUri ?? asset.uri, [], { base64: true });
return `
<html>
<img
src="data:image/jpeg;base64,${image.base64}"
style="width: 90vw;" />
</html>
`;
}
async function print() {
const html = await generateHTML();
await printAsync({ html });
}
On iOS you can set the page margins using the margins
option:
const { uri } = await Print.printToFileAsync({
html: 'This page is printed with margins',
margins: {
left: 20,
top: 50,
right: 20,
bottom: 100,
},
});
If useMarkupFormatter
is set to true
, setting margins may cause a blank page to appear at the end of your printout. To prevent this, make sure your HTML string is a well-formed document, including <!DOCTYPE html>
at the beginning of the string.
On Android, if you're using html
option in printAsync
or printToFileAsync
, the resulting print might contain page margins (it depends on the WebView engine).
They are set by @page
style block and you can override them in your HTML code:
<style>
@page {
margin: 20px;
}
</style>
See @page
documentation on MDN for more details.