Expo 打印
一个为 Android 和 iOS(AirPrint)提供打印功能的库。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
expo-print 提供了 Android 和 iOS(AirPrint)打印功能的 API。
安装
- npx expo install expo-printIf you are installing this in an existing React Native app, make sure to install expo in your project.
使用
import { useState } 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://docs.expo.dev/static/images/expo-logo.svg" style="width: 90vw;" /> </body> </html> `; export default function App() { const [selectedPrinter, setSelectedPrinter] = useState(); const print = async () => { // 在 iOS/Android 上打印给定的 html。在 web 上打印当前页面的 HTML。 await Print.printAsync({ html, printerUrl: selectedPrinter?.url, // 仅限 iOS }); }; const printToFile = async () => { // 在 iOS/Android 上打印给定的 html。在 web 上打印当前页面的 HTML。 const { uri } = await Print.printToFileAsync({ html }); console.log('文件已保存到:', uri); await shareAsync(uri, { UTI: '.pdf', mimeType: 'application/pdf' }); }; const selectPrinter = async () => { const printer = await Print.selectPrinterAsync(); // 仅限 iOS 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> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', backgroundColor: '#ecf0f1', flexDirection: 'column', padding: 8, }, spacer: { height: 8, }, printer: { textAlign: 'center', }, });
API
import * as Print from 'expo-print';
Constants
Methods
| Parameter | 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
WKWebViewlimitations). As a workaround you can use inlined base64-encoded strings. See this comment for more details.
Note: on iOS, when printing without providing a
PrintOptions.printerUrlthePromisewill be resolved once printing is started in the native print window and rejected if the window is closed without starting the print. On Android thePromisewill be resolved immediately after displaying the native print window and won't be rejected if the window is closed without starting the print.
Promise<void>Resolves to an empty Promise if printing started.
| Parameter | 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.
Promise<FilePrintResult>Interfaces
The possible values of orientation for the printed content.
| Property | Type | Description |
|---|---|---|
| landscape | string | - |
| portrait | string | - |
Types
| Property | 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. |
| textZoom(optional) | number | Only for: Android The text zoom of the page in percent. The default is 100. |
| 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 |
| Property | 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. |
| Property | Type | Description |
|---|---|---|
| name | string | Name of the printer. |
| url | string | URL of the printer. |
| Property | 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: Android 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 |
本地图片
在 iOS 上,从 HTML 源打印不支持本地资源 URL(由于 WKWebView 的限制)。作为替代,图片需要转换为 base64 并内联到 HTML 中。
import { Asset } from 'expo-asset'; import { useImageManipulator } from 'expo-image-manipulator'; import { printAsync } from 'expo-print'; import { useEffect } from 'react'; const IMAGE = Asset.fromModule(require('@/assets/images/icon.png')); export function ImageManipulatorExample() { const context = useImageManipulator(IMAGE.uri); useEffect(() => { async function generateAndPrint() { try { await IMAGE.downloadAsync(); const manipulatedImage = await context.renderAsync(); const result = await manipulatedImage.saveAsync({ base64: true }); const html = ` <html> <img src="data:image/png;base64,${result.base64}" style="width: 90vw;" /> </html> `; await printAsync({ html }); } catch (error) { console.error('错误:', error); } } generateAndPrint(); }, [context]); return <>{/* 渲染 UI */}</>; }
页面边距
在 iOS 上,你可以使用 margins 选项设置页面边距:
const { uri } = await Print.printToFileAsync({ html: '此页面将使用边距进行打印', margins: { left: 20, top: 50, right: 20, bottom: 100, }, });
如果 useMarkupFormatter 设置为 true,设置边距可能会导致打印输出末尾出现空白页。为避免这种情况,请确保你的 HTML 字符串是一个格式正确的文档,并在字符串开头包含 <!DOCTYPE html>。
在 Android 上,如果你在 printAsync 或 printToFileAsync 中使用 html 选项,生成的打印内容可能包含页面边距(这取决于 WebView 引擎)。
它们由 @page 样式块设置,你可以在 HTML 代码中覆盖它们:
<style> @page { margin: 20px; } </style>
更多详情请参见 MDN 上的 @page 文档。