目录
1 概述
PDF Kit(PDF服务)包含pdfService和PdfView组件。
pdfService提供了加载和保存PDF文档、在PDF页面中添加文本内容、图片、批注、页眉页脚、水印、背景图片、书签、判断PDF文档是否加密及删除文档加密等相关的功能,对PDF文档的操作有更多的应用场景。
PdfView组件提供了文档预览功能,如:PDF文档预览、高亮显示、搜索关键字,批注等场景。
1.1 pdfService与PdfView能力比较
PDF Kit能力 | pdfService是否支持 | PdfView预览组件是否支持 |
---|---|---|
打开和保存文档 | 支持 | 支持 |
释放文档 | 支持 | 支持 |
PDF文档转图片 | 支持 | 支持 |
添加、删除批注 | 支持 | 支持 |
管理书签 | 支持 | 不支持 |
添加、编辑、删除PDF页 | 支持 | 不支持 |
添加、删除文本内容 | 支持 | 不支持 |
添加、删除图片内容 | 支持 | 不支持 |
编辑页眉页脚、水印、背景 | 支持 | 不支持 |
判断PDF文档是否加密 | 支持 | 不支持 |
删除文档加密 | 支持 | 不支持 |
PDF文档预览 | 不支持 | 支持 |
搜索关键字 | 不支持 | 支持 |
PDF文档监听回调 | 不支持 | 支持 |
1.2 约束与限制
1.2.1 支持的设备
当前PDF Kit相关能力只支持在真机上运行,华为Phone、Tablet和2in1,暂不支持在模拟器上运行。
2 pdfService能力
2.1 打开和保存PDF文档
对PDF文档添加内容、页眉页脚、水印、背景图片或书签等操作前,需要打开文档,并且在文档操作完成后,保存PDF文档。
pdfService和PdfView都可实现打开和保存文档,使用场景上有如下区别:
- 需要对PDF文档做相关的编辑和操作,建议使用pdfService的能力打开和保存文档。
- 需要预览、搜索关键字、监听PDF文档回调和批注等操作,推荐使用PdfView打开。
2.1.1 接口说明
接口名 | 描述 |
---|---|
loadDocument(path: string, password?: string, onProgress?: Callback<number>): ParseResult | 加载指定文档路径。 |
saveDocument(path: string, onProgress?: Callback<number>): boolean | 保存文档。 |
2.1.2 示例代码
- 调用loadDocument方法,加载PDF文档。
- 在【Save As】和【Save】两个按钮中调用saveDocument方法,分别实现了另存为PDF文档和保存覆盖源PDF文档的两种方式。
import { common } from '@kit.AbilityKit';
import { pdfService } from '@kit.PDFKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { fileIo } from '@kit.CoreFileKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
private filePath = '';
@State saveEnable: boolean = false;
aboutToAppear(): void {
this.filePath = this.context.filesDir + '/input.pdf';
let res = fileIo.accessSync(this.filePath);
if(!res) {
// 确保在工程目录src/main/resources/rawfile里有input.pdf文档
let content: Uint8Array = this.context.resourceManager.getRawFileContentSync('rawfile/input.pdf');
let fdSand =
fileIo.openSync(this.filePath, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE | fileIo.OpenMode.TRUNC);
fileIo.writeSync(fdSand.fd, content.buffer);
fileIo.closeSync(fdSand.fd);
}
this.pdfDocument.loadDocument(this.filePath);
}
build() {
Column() {
// 另存为一份PDF文档
Button('Save As').onClick(() => {
// 可以对PDF文档添加页眉页脚,水印,背景等一些内容,然后另存文档
let outPdfPath = this.context.filesDir + '/testSaveAsPdf.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
this.saveEnable = true;
hilog.info(0x0000, 'PdfPage', 'saveAsPdf %{public}s!', result ? 'success' : 'fail');
})
// 保存覆盖源PDF文档
Button('Save').enabled(this.saveEnable).onClick(() => {
// 这里可以对PDF文档添加内容、页眉页脚、水印、背景等一些内容,然后保存文档
let tempDir = this.context.tempDir;
let tempFilePath = tempDir + `/temp${Math.random()}.pdf`;
fileIo.copyFileSync(this.filePath, tempFilePath);
let pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
// 加载临时文档
let loadResult = pdfDocument.loadDocument(tempFilePath, '');
if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let result = pdfDocument.saveDocument(this.filePath);
hilog.info(0x0000, 'PdfPage', 'savePdf %{public}s!', result ? 'success' : 'fail');
}
})
}
}
}
2.2 添加、删除PDF页
在PDF文档中添加或删除页面,包括:
- 添加单个、多个空白页到PDF文档。
- 删除PDF文档中单个、多个指定页。
- 将其他PDF文档页添加到本PDF文档。
2.2.1 接口说明
接口名 | 描述 |
---|---|
insertBlankPage(index: number, width: number, height: number): PdfPage | 在指定位置插入空白PDF页。 |
getPage(index: number): PdfPage | 获取指定页的对象。 |
insertPageFromDocument(document: PdfDocument, fromIndex: number, pageCount: number, index: number): PdfPage | 将其他文档的页添加到当前文档。 |
deletePage(index: number, count: number): void | 删除指定的PDF页。 |
2.2.2 示例代码
- 调用loadDocument方法,加载PDF文档。
- 调用getPage方法获取当前页,用于获取页面宽高。
- 调用insertBlankPage和insertPageFromDocument方法实现如下功能。
- 插入单个空白页。
- 插入多个空白页。
- 将input2.pdf文档的索引1、2、3页插入到input.pdf索引0的位置,并另存文档。
- 调用deletePage方法删除单个或多个索引页。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.pdfDocument.loadDocument(filePath);
}
build() {
Column() {
// 插入单个空白页
Button('insertBankPage').onClick(async () => {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let page2: pdfService.PdfPage = this.pdfDocument.insertBlankPage(2, page.getWidth(), page.getHeight());
let outPdfPath = this.context.filesDir + '/testInsertBankPage.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'insertBankPage %{public}s!', result ? 'success' : 'fail');
})
// 插入多个空白页
Button('insertSomeBankPage').onClick(async () => {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
for (let i = 0; i < 3; i++) {
this.pdfDocument.insertBlankPage(2, page.getWidth(), page.getHeight());
}
let outPdfPath = this.context.filesDir + '/testInsertSomeBankPage.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'insertSomeBankPage %{public}s!', result ? 'success' : 'fail');
})
// 将input2.pdf文档的索引1,2,3页插入到input.pdf索引0的位置,并另存文档
Button('insertPageFromDocument').onClick(async () => {
let pdfDoc: pdfService.PdfDocument = new pdfService.PdfDocument();
// 确保该沙箱目录下有 input2.pdf文档
pdfDoc.loadDocument(this.context.filesDir + '/input2.pdf');
this.pdfDocument.insertPageFromDocument(pdfDoc, 1, 3, 0);
let outPdfPath = this.context.filesDir + '/testInsertPageFromDocument.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'insertPageFromDocument %{public}s!', result ? 'success' : 'fail');
})
// 删除单个或多个索引页
Button('deletePage').onClick(async () => {
this.pdfDocument.deletePage(2, 2);
let outPdfPath = this.context.filesDir + '/testDeletePage.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'deletePage %{public}s!', result ? 'success' : 'fail');
})
}
}
}
2.3 PDF页面文本、图片和批注
支持编辑PDF页面内容,包括:
- 添加、删除文本。
- 添加、删除图片。
- 添加、修改、删除批注。
通过索引指定PDF页面添加批注,并对批注在页面中的位置,字体、批注边框等设置,批注提供了多种风格样式,包括:文本批注TextAnnotationInfo、下划线批注LineAnnotationInfo、高亮批注HighlightAnnotationInfo、删除线批注StrikethroughAnnotationInfo等共13种。
2.3.1 接口说明
接口名 | 描述 |
---|---|
addTextObject(text: string, x: number, y: number, style: TextStyle): void | 添加文本内容,只可按行添加。 |
addImageObject(path: string, x: number, y: number, width: number, height: number): void | 在PDF文档的页面中添加图片。 |
deleteGraphicsObject(object: GraphicsObject): void | 删除指定的GraphicsObject。 |
addAnnotation(annotationInfo: PdfAnnotationInfo): PdfAnnotation | 在当前页添加批注。 |
2.3.2 添加文本和图片
- 调用loadDocument方法,加载PDF文档。
- 在【addText】按钮中调用addTextObject的方法插入文本。
- 在【delText】按钮中调用deleteGraphicsObject方法来删除相应的页面文本。
- 在【addImage】按钮中调用addImageObject的方法插入图片。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { font } from '@kit.ArkUI';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.pdfDocument.loadDocument(filePath);
}
build() {
Column() {
// 添加文本
Button('addText').onClick(async () => {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let str = 'This is add text object!';
let fontInfo = new pdfService.FontInfo();
// 确保字体路径存在
fontInfo.fontPath = font.getFontByName('HarmonyOS Sans')?.path;
fontInfo.fontName = '';
let style: pdfService.TextStyle = { textColor: 0x000000, textSize: 30, fontInfo };
page.addTextObject(str, 10, 10, style);
let outPdfPath = this.context.filesDir + '/testAddText.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addText %{public}s!', result ? 'success' : 'fail');
})
// 删除文本
Button('delText').onClick(async () => {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let graphicsObjects = page.getGraphicsObjects();
// 找到第一个要删除的文本
let index = graphicsObjects.findIndex(item => item.type === pdfService.GraphicsObjectType.OBJECT_TEXT);
if (index > -1) {
// 删除第一个文本
page.deleteGraphicsObject(graphicsObjects[index]);
}
let outPdfPath = this.context.filesDir + '/testDelText.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'delText %{public}s!', result ? 'success' : 'fail');
})
// 添加图片
Button('addImage').onClick(async () => {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
// 插入图片,确保沙箱目录有img.jpg图片
let imagePath = this.context.filesDir + '/img.jpg';
page.addImageObject(imagePath, 100, 100, 100, 120);
let outPdfPath = this.context.filesDir + '/testAddImage.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addImage %{public}s!', result ? 'success' : 'fail');
})
}
}
}
2.3.3 添加文本批注
- 调用loadDocument方法,加载PDF文档。
- 调用getPage方法获取指定页。
- 实例化TextAnnotationInfo文本批注,并设置相关属性。
- 调用addAnnotation或setAnnotation方法添加或修改批注。
- 调用removeAnnotation方法删除批注。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
// 添加批注
Button('addTextAnnotation').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.pdfDocument.loadDocument(filePath);
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let aInfo = new pdfService.TextAnnotationInfo();
aInfo.iconName = 'cument Format';
aInfo.content = 'this is a content';
aInfo.subject = 'Annotation';
aInfo.title = 'this is a title';
aInfo.state = pdfService.TextAnnotationState.MARKED;
aInfo.x = 200;
aInfo.y = 200;
aInfo.color = 0xf9b1b1;
aInfo.flag = pdfService.AnnotationFlag.PRINTED;
let annotation: pdfService.PdfAnnotation = page.addAnnotation(aInfo);
let outPdfPath = this.context.filesDir + '/testAddTextAnnotation.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
this.pdfDocument.releaseDocument();
hilog.info(0x0000, 'PdfPage', 'addTextAnnotation %{public}s!', result ? 'success' : 'fail');
})
// 修改批注
Button('setAnnotation').onClick(async () => {
let filePath = this.context.filesDir + '/testAddTextAnnotation.pdf';
let result = this.pdfDocument.loadDocument(filePath);
if (result === pdfService.ParseResult.PARSE_SUCCESS) {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let annotations = page.getAnnotations();
if (annotations.length > 0 && annotations[0].type === pdfService.AnnotationType.TEXT) {
let newAnno = annotations[0];
page.removeAnnotation(newAnno);
let annotation = page.addAnnotation(newAnno);
let newInfo = new pdfService.TextAnnotationInfo();
newInfo.title = "new Title";
newInfo.content = "new Info";
newInfo.state = pdfService.TextAnnotationState.MARKED;
newInfo.x = 100;
newInfo.y = 100;
page.setAnnotation(annotation, newInfo);
let outPdfPath = this.context.filesDir + '/testSetAnnotation.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
this.pdfDocument.releaseDocument();
hilog.info(0x0000, 'PdfPage', 'setAnnotation %{public}s!', result ? 'success' : 'fail');
}
}
})
// 删除批注
Button('removeAnnotation').onClick(async () => {
let filePath = this.context.filesDir + '/testAddTextAnnotation.pdf';
let result = this.pdfDocument.loadDocument(filePath);
if (result === pdfService.ParseResult.PARSE_SUCCESS) {
let page: pdfService.PdfPage = this.pdfDocument.getPage(0);
let annotations = page.getAnnotations();
if (annotations.length > 0 && annotations[0].type === pdfService.AnnotationType.TEXT) {
page.removeAnnotation(annotations[0]);
let outPdfPath = this.context.filesDir + '/testRemoveAnnotation.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
this.pdfDocument.releaseDocument();
hilog.info(0x0000, 'PdfPage', 'removeAnnotation %{public}s!', result ? 'success' : 'fail');
}
}
})
}
}
}
2.4 转换PDF文档指定页面或指定区域为图片
2.4.1 场景介绍
PDF文档页面转换为图片,或将页面的指定区域转换为图片时使用。
2.4.2 接口说明
接口名 | 描述 |
---|---|
getPagePixelMap(): image.PixelMap | 获取当前页的图片。 |
getCustomPagePixelMap(matrix: PdfMatrix, isGray: boolean, drawAnnotations: boolean): image.PixelMap | 获取指定PdfPage区域的图片内容。 |
getAreaPixelMap(matrix: PdfMatrix, bitmapwidth: number, bitmapHeight: number, isGray: boolean, drawAnnotations: boolean): image.PixelMap | 获取指定PdfPage区域的图片内容,并指定图片的宽和高。 |
2.4.3 示例代码
- 调用loadDocument方法加载PDF文档。
- 调用getPage方法获取某个页面。
- 调用getPagePixelMap或getCustomPagePixelMap方法获取当前页面或者页面区域,这时获取的是image.PixelMap图像类型。
- 将image.PixelMap图像类型转化为二进制图片文件并保存,参考以下方法pixelMap2Buffer。
import { pdfService } from '@kit.PDFKit';
import { image } from '@kit.ImageKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.loadResult = this.pdfDocument.loadDocument(filePath);
}
// 将 pixelMap 转成图片格式
pixelMap2Buffer(pixelMap: image.PixelMap): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
/**
设置打包参数
format:图片打包格式,只支持 jpg 和 webp
quality:JPEG 编码输出图片质量
bufferSize:图片大小,默认 10M
*/
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 }
// 创建ImagePacker实例
const imagePackerApi = image.createImagePacker()
imagePackerApi.packToData(pixelMap, packOpts).then((buffer: ArrayBuffer) => {
resolve(buffer)
}).catch((err: BusinessError) => {
reject()
})
})
}
build() {
Column() {
// 获取为图片并保存到应用沙箱
Button('getPagePixelMap').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let page = this.pdfDocument.getPage(0)
let pixmap: image.PixelMap = page.getPagePixelMap();
if (!pixmap) {
return
}
const imgBuffer = await this.pixelMap2Buffer(pixmap)
const file =
fs.openSync(this.context.filesDir + `/${Date.now()}.png`, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, imgBuffer)
// 关闭文档
await fs.close(file.fd)
}
})
// 获取指定PdfPage区域的图片内容。
Button('getCustomPagePixelMap').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let page = this.pdfDocument.getPage(0);
let matrix = new pdfService.PdfMatrix();
matrix.x = 100;
matrix.y = 100;
matrix.width = 500;
matrix.height = 500;
matrix.rotate = 0;
let pixmap: image.PixelMap = page.getCustomPagePixelMap(matrix, false, false);
if (!pixmap) {
return;
}
const imgBuffer = await this.pixelMap2Buffer(pixmap);
const file =
fs.openSync(this.context.filesDir + `/${Date.now()}.jpeg`, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, imgBuffer);
// 关闭文件
await fs.close(file.fd);
}
})
// 获取指定PdfPage区域的图片内容
Button('getAreaPixelMap').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let page = this.pdfDocument.getPage(0);
let matrix = new pdfService.PdfMatrix();
matrix.x = 100;
matrix.y = 100;
matrix.width = 500;
matrix.height = 500;
matrix.rotate = 0;
let pixmap: image.PixelMap = page.getAreaPixelMap(matrix, 400, 400, true, false);
if (!pixmap) {
return
}
const imgBuffer = await this.pixelMap2Buffer(pixmap)
const file =
fs.openSync(this.context.filesDir + `/${Date.now()}.bmp`, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, imgBuffer)
// 关闭文件
await fs.close(file.fd);
}
})
}
}
}
2.5 转换整个PDF文档为图片
2.5.1 场景介绍
将整个PDF文档的页面转换为图片,每页为一张图片,并且所有图片存放在指定的同一个文件夹下。
2.5.2 接口说明
接口名 | 描述 |
---|---|
convertToImage(path: string, format: ImageFormat, onProgress?: Callback<number>): boolean | 转换PDF文档为图片。 |
2.5.3 示例代码
- 调用loadDocument方法,加载PDF文档。
- 设置要输出图片的文件夹,调用convertToImage方法转化PDF文档所有页面为图片。
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { pdfService } from '@kit.PDFKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.loadResult = this.pdfDocument.loadDocument(filePath);
}
build() {
Column() {
// 获取为图片并保存到应用沙箱
Button('convertToImage').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let outputPath = getContext().filesDir + '/output/';
fs.mkdir(outputPath);
// 将所有的页面转化为png图片,并存储在output文件夹里
let res = this.pdfDocument.convertToImage(outputPath, pdfService.ImageFormat.PNG);
hilog.info(0x0000, 'PdfPage', 'convertToImage %{public}s!', res ? 'success' : 'fail');
}
})
}
}
}
2.6 判断PDF文档是否加密及删除加密
PDF Kit支持判断PDF文档是否加密及删除PDF加密锁。
当前PDF Kit不支持PDF文档加密。
2.6.1 接口说明
接口名 | 描述 |
---|---|
isEncrypted(path: string): boolean | 判断当前文档是否已加密。 |
removeSecurity(): boolean | 删除文档加密锁。 |
2.6.2 示例代码
- 调用isEncrypted方法,判断的PDF文档是否加密。
- 如果是加密PDF文档,调用removeSecurity方法移除PDF文档的加密锁。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
// 判断文档是否加密,并删除加密
Button('isEncryptedAndRemoveSecurity').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
let isEncrypt = this.pdfDocument.isEncrypted(filePath);
if (isEncrypt) {
let hasRemoveEncrypt = this.pdfDocument.removeSecurity();
hilog.info(0x0000, 'PdfPage', 'isEncryptedAndRemoveSecurity %{public}s!',
hasRemoveEncrypt ? 'success' : 'fail');
}
})
}
}
}
2.7 添加、删除书签
PDF Kit支持添加和删除PDF文档书签。
添加书签时,可设置标题、颜色,是否粗体、斜体、跳转信息等。
2.7.1 接口说明
接口名 | 描述 |
---|---|
createBookmark(): Bookmark | 创建PDF文档书签。 |
getRootBookmark(): Bookmark | 获取PDF文档第一个根书签。 |
insertBookmark(bookmark: Bookmark, parent: Bookmark, position: number): boolean | 插入PDF文档书签。 |
setBookmarkInfo(info: BookmarkInfo): void | 设置书签信息。 |
removeBookmark(bookmark: Bookmark): boolean | 移除PDF文档书签。 |
2.7.2 示例代码
- 调用loadDocument方法,加载PDF文档。
- 调用createBookmark方法,创建书签。
- 调用setDestInfo方法,设置书签的跳转信息。
- 调用setBookmarkInfo方法,设置书签内容及样式。
- 设置保存文档沙箱路径并保存。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
// 添加书签
Button('addBookmark').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
this.pdfDocument.loadDocument(filePath);
// 创建书签
let mark1: pdfService.Bookmark = this.pdfDocument.createBookmark();
let mark2: pdfService.Bookmark = this.pdfDocument.createBookmark();
// 设置书签的跳转信息
let destInfo: pdfService.DestInfo = mark1.getDestInfo();
destInfo.fitMode = pdfService.FitMode.FIT_MODE_XYZ;
destInfo.pageIndex = 1;
destInfo.left = 20;
destInfo.top = 30;
destInfo.zoom = 1.5;
mark1.setDestInfo(destInfo);
// 设置书签内容及样式
let bookInfo: pdfService.BookmarkInfo = mark1.getBookmarkInfo();
bookInfo.title = '这里是跳到第一页的书签';
bookInfo.titleColor = 12;
bookInfo.isBold = true;
bookInfo.isItalic = true;
mark1.setBookmarkInfo(bookInfo);
// 把创建的书签插入到PDF页面
this.pdfDocument.insertBookmark(mark1, null, 1);
this.pdfDocument.insertBookmark(mark2, mark1, 1);
// 设置保存文档沙箱路径并保存
let outPdfPath = this.context.filesDir + '/testAddBookmark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'saveAddBookmark %{public}s!', result ? 'success' : 'fail');
})
// 删除书签
Button('removeBookmark').onClick(async () => {
// 确保沙箱目录有testAddBookmark.pdf文档
this.pdfDocument.loadDocument(this.context.filesDir + '/testAddBookmark.pdf');
let bookmarks: pdfService.Bookmark = this.pdfDocument.getRootBookmark();
if (bookmarks.isRootBookmark()) {
let hasRemoveBookmark: boolean = this.pdfDocument.removeBookmark(bookmarks);
hilog.info(0x0000, 'PdfPage', 'removeBookmark %{public}s!', hasRemoveBookmark ? 'success' : 'fail');
let outPdfPath = this.context.filesDir + '/testRemoveBookmark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'saveRemoveBookmark %{public}s!', result ? 'success' : 'fail');
}
})
}
}
}
2.8 添加、删除页眉页脚
PDF Kit支持对指定页面添加、删除页眉页脚。页眉页脚信息包含文字、日期和页码等相关内容,并可设置字体大小、颜色和间距等相关样式,具体属性参考HeaderFooterInfo。如下图:
2.8.1 接口说明
接口名 | 描述 |
---|---|
addHeaderFooter(info: HeaderFooterInfo, startIndex: number, endIndex: number, oddPages: boolean, evenPages: boolean): void | 插入PDF文档页眉页脚。 |
removeHeaderFooter(): boolean | 删除PDF文档页眉页脚。 |
注意
addHeaderFooter方法属于耗时业务,需要遍历每一页去添加页眉页脚,添加页面较多时建议放到线程里去处理。
2.8.2 示例代码
- 调用loadDocument方法,加载PDF文档。
- 实例化页眉页脚HeaderFooterInfo类,并设置相关属性,包括字体大小、颜色和间距等。
- 调用addHeaderFooter方法,添加页眉页脚到页面中。
- 保存PDF文档到应用沙箱。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { font } from '@kit.ArkUI';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
Button('addHeaderFooter').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS) {
let hfInfo: pdfService.HeaderFooterInfo = new pdfService.HeaderFooterInfo();
hfInfo.fontInfo = new pdfService.FontInfo();
// 确保字体路径存在
hfInfo.fontInfo.fontPath = font.getFontByName('HarmonyOS Sans')?.path;
// 如果不知道字体的具体名称,可以为空字符串
hfInfo.fontInfo.fontName = '';
hfInfo.textSize = 10;
hfInfo.charset = pdfService.CharsetType.PDF_FONT_DEFAULT_CHARSET;
hfInfo.underline = false;
hfInfo.textColor = 0x00000000;
hfInfo.leftMargin = 1.0;
hfInfo.topMargin = 40.0;
hfInfo.rightMargin = 1.0;
hfInfo.bottomMargin = 40.0;
hfInfo.headerLeftText = 'left H <<dd.mm.yyyy>> <<1/n>>';
hfInfo.headerCenterText = 'center H <<m/d/yyyy>> <<1/n>>';
hfInfo.headerRightText = 'right H <<m/d>><<1>>';
hfInfo.footerLeftText = 'left F <<m/d>><<1>>';
hfInfo.footerCenterText = 'center F <<m/d>><<1>>';
hfInfo.footerRightText = 'right F <<dd.mm.yyyy>><<1>>';
this.pdfDocument.addHeaderFooter(hfInfo, 1, 5, true, true);
let outPdfPath = this.context.filesDir + '/testAddHeaderFooter.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addHeaderFooter %{public}s!', result ? 'success' : 'fail');
}
this.pdfDocument.releaseDocument();
})
Button('removeHeaderFooter').onClick(async () => {
let filePath = this.context.filesDir + '/testAddHeaderFooter.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS && this.pdfDocument.hasHeaderFooter()) {
let removeResult = this.pdfDocument.removeHeaderFooter();
if (removeResult) {
let outPdfPath = this.context.filesDir + '/removeHeaderFooter.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'removeHeaderFooter %{public}s!', result ? 'success' : 'fail');
}
}
this.pdfDocument.releaseDocument();
})
}
}
}
2.9 添加、删除水印
对指定页面添加水印,包括文本水印或图片水印。
- 文本水印可以设置字体、大小、旋转,位置等属性。
- 图片水印可以设置缩放、旋转、透明度和位置等属性。
2.9.1 接口说明
接口名 | 描述 |
---|---|
addWatermark(info: WatermarkInfo, startIndex: number, endIndex: number, oddPages: boolean, evenPages: boolean): void | 插入水印到PDF文档。如果插入的是图片,支持的图片格式参考ImageFormat,文本字符无限制。 |
removeWatermark(): boolean | 删除PDF文档水印。 |
注意
addWatermark方法属于耗时业务,需要遍历每一页去添加水印,添加页面较多时建议放到线程里去处理。
2.9.2 示例代码
1、添加文本水印
- 调用loadDocument方法,加载PDF文档。
- 实例化文本水印TextWatermarkInfo类,并设置相关属性,包括字体、大小、旋转,位置等。
- 调用addWatermark或removeWatermark,添加或删除文本水印。
- 保存PDF文档到应用沙箱。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { font } from '@kit.ArkUI';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
Button('addTextWatermark').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS) {
let wminfo: pdfService.TextWatermarkInfo = new pdfService.TextWatermarkInfo();
wminfo.watermarkType = pdfService.WatermarkType.WATERMARK_TEXT;
wminfo.content = 'This is Watermark';
wminfo.textSize = 30;
wminfo.textColor = 200;
wminfo.fontInfo = new pdfService.FontInfo();
// 确保字体路径存在
wminfo.fontInfo.fontPath = font.getFontByName('HarmonyOS Sans').path;
wminfo.opacity = 0.5;
wminfo.isOnTop = true;
wminfo.rotation = 45;
wminfo.scale = 1.5;
wminfo.opacity = 0.5;
wminfo.verticalAlignment = pdfService.WatermarkAlignment.WATERMARK_ALIGNMENT_TOP;
wminfo.horizontalAlignment = pdfService.WatermarkAlignment.WATERMARK_ALIGNMENT_LEFT;
wminfo.horizontalSpace = 1.0;
wminfo.verticalSpace = 1.0;
this.pdfDocument.addWatermark(wminfo, 0, 5, true, true);
let outPdfPath = this.context.filesDir + '/testTextWatermark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addTextWatermark %{public}s!', result ? 'success' : 'fail');
}
this.pdfDocument.releaseDocument();
})
Button('removeTextWatermark').onClick(async () => {
let filePath = this.context.filesDir + '/testTextWatermark.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS && this.pdfDocument.hasWatermark()) {
let removeResult = this.pdfDocument.removeWatermark();
if (removeResult) {
let outPdfPath = this.context.filesDir + '/removeWatermark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'removeWatermark %{public}s!', result ? 'success' : 'fail');
}
}
this.pdfDocument.releaseDocument();
})
}
}
}
2、添加图片水印
- 调用loadDocument方法加载PDF文档。
- 实例化图片水印ImageWatermarkInfo类,并设置相关属性,包括缩放、旋转、透明度和位置等。
- 调用addWatermark或removeWatermark添加或删除图片水印。
- 保存PDF文档到应用沙箱。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
Button('addImageWatermark').onClick(async () => {
let filePath = this.context.filesDir + '/input.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS) {
let wminfo: pdfService.ImageWatermarkInfo = new pdfService.ImageWatermarkInfo();
wminfo.watermarkType = pdfService.WatermarkType.WATERMARK_IMAGE;
// 确保沙箱目录有img.jpg文档
wminfo.imagePath = this.context.filesDir + '/img.jpg';
wminfo.opacity = 0.5;
wminfo.isOnTop = true;
wminfo.rotation = 45;
wminfo.scale = 0.5;
wminfo.opacity = 0.5;
wminfo.verticalAlignment = pdfService.WatermarkAlignment.WATERMARK_ALIGNMENT_TOP;
wminfo.horizontalAlignment = pdfService.WatermarkAlignment.WATERMARK_ALIGNMENT_LEFT;
wminfo.horizontalSpace = 1.0;
wminfo.verticalSpace = 1.0;
this.pdfDocument.addWatermark(wminfo, 0, 5, true, true);
let outPdfPath = this.context.filesDir + '/testImageWatermark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addImageWatermark %{public}s!', result ? 'success' : 'fail');
}
this.pdfDocument.releaseDocument();
})
Button('removeImageWatermark').onClick(async () => {
let filePath = this.context.filesDir + '/testImageWatermark.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS && this.pdfDocument.hasWatermark()) {
let removeResult = this.pdfDocument.removeWatermark();
if (removeResult) {
let outPdfPath = this.context.filesDir + '/removeImageWatermark.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'removeImageWatermark %{public}s!', result ? 'success' : 'fail');
}
}
this.pdfDocument.releaseDocument();
})
}
}
}
2.10 添加、删除背景
对指定页面添加背景图片或背景颜色,并设置大小、旋转、透明度和位置等属性,支持图片格式:PNG、BMP、JPEG。
2.10.1 接口说明
接口名 | 描述 |
---|---|
addBackground(info: BackgroundInfo, startIndex: number, endIndex: number, oddPages: boolean, evenPages: boolean): void | 插入PDF文档背景。 |
removeBackground(): boolean | 删除PDF文档背景。 |
注意
addBackground方法属于耗时业务,需要遍历每一页去添加背景,添加页面较多时建议放到线程里去处理。
2.10.2 示例代码
- 调用loadDocument方法,加载PDF文档。
- 实例化背景BackgroundInfo类,并设置相关属性,包括大小、旋转、透明度和位置等。
- 保存PDF文档到应用沙箱。
import { pdfService } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
private context = getContext() as common.UIAbilityContext;
build() {
Column() {
Button('addBackground').onClick(async () => {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS) {
let bginfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
// 确保沙箱目录有img.jpg文档
bginfo.imagePath = this.context.filesDir + '/img.jpg';
bginfo.backgroundColor = 50;
bginfo.isOnTop = true;
bginfo.rotation = 45;
bginfo.scale = 0.5;
bginfo.opacity = 0.3;
bginfo.verticalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_TOP;
bginfo.horizontalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_LEFT;
bginfo.horizontalSpace = 1.0;
bginfo.verticalSpace = 1.0;
this.pdfDocument.addBackground(bginfo, 0, 2, true, true);
let outPdfPath = this.context.filesDir + '/testAddBackground.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'addBackground %{public}s!', result ? 'success' : 'fail');
}
this.pdfDocument.releaseDocument();
})
Button('removeBackground').onClick(async () => {
let filePath = this.context.filesDir + '/testAddBackground.pdf';
let res = this.pdfDocument.loadDocument(filePath);
if (res === pdfService.ParseResult.PARSE_SUCCESS && this.pdfDocument.hasBackground()) {
let removeResult = this.pdfDocument.removeBackground();
if (removeResult) {
let outPdfPath = this.context.filesDir + '/removeBackground.pdf';
let result = this.pdfDocument.saveDocument(outPdfPath);
hilog.info(0x0000, 'PdfPage', 'removeBackground %{public}s!', result ? 'success' : 'fail');
}
}
this.pdfDocument.releaseDocument();
})
}
}
}
3 PdfView预览组件
3.1 预览PDF文档
PDF Kit提供了丰富的PDF文档预览能力,比如:
- 页面跳转
- 页面缩放
- 单双页显示
- 页面适配
- 滚动视图方式预览
3.1.1 示例代码
- 导入相关模块。
- 以下示例代码中以预览“input.pdf”文件名为例,此时需要确保在工程目录“src/main/resources/rawfile”里存在input.pdf文档,并且拷贝input.pdf文档到沙箱目录。
- 调用loadDocument方法,加载PDF文档。
- 调用PdfView预览组件,渲染显示。
import { pdfService, pdfViewManager, PdfView } from '@kit.PDFKit'
import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct Index {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
aboutToAppear(): void {
let context = getContext() as common.UIAbilityContext;
let dir: string = context.filesDir
// 确保在工程目录src/main/resources/rawfile里存在input.pdf文档
let filePath: string = dir + '/input.pdf';
let res = fileIo.accessSync(filePath);
if (!res) {
let content: Uint8Array = context.resourceManager.getRawFileContentSync('rawfile/input.pdf');
let fdSand =
fileIo.openSync(filePath, fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE | fileIo.OpenMode.TRUNC);
fileIo.writeSync(fdSand.fd, content.buffer);
fileIo.closeSync(fdSand.fd);
}
(async () => {
// 该监听方法只能在文档加载前调用一次
this.controller.registerPageCountChangedListener((pageCount: number) => {
hilog.info(0x0000, 'registerPageCountChanged-', pageCount.toString());
});
let loadResult1: pdfService.ParseResult = await this.controller.loadDocument(filePath);
// 注意:这里刚加载文档,请不要在这里立即设置PDF文档的预览方式
})()
}
build() {
Row() {
PdfView({
controller: this.controller,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
.width('100%')
.height('100%')
}
}
3.2 打开和保存PDF文档
3.2.1 场景介绍
通过加载本地路径的PDF文档,实现打开PDF文档的预览功能。当PDF文档做了批注等相关的信息时,可以使用保存功能。
3.2.2 接口说明
接口名 | 描述 |
---|---|
loadDocument(path: string, password?: string, initPageIndex?: number, onProgress?: Callback<number>): Promise<ParseResult> | 加载PDF文档。 |
saveDocument(path: string, onProgress?: Callback<number>): Promise<number> | 保存PDF文档,使用Promise异步回调。 |
3.2.3 示例代码
- 在aboutToAppear函数里面加载PDF文档。
- 调用PdfView预览组件,渲染显示。
- 在【savePdfDocument】按钮中调用saveDocument方法另存PDF文档。
import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
this.loadResult = await this.controller.loadDocument(filePath);
})()
}
build() {
Column() {
// 保存Pdf文档
Button('savePdfDocument').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let savePath = this.context.filesDir + '/savePdfDocument.pdf';
let result = await this.controller.saveDocument(savePath);
hilog.info(0x0000, 'PdfPage', 'savePdfDocument %{public}s!', result ? 'success' : 'fail');
}
})
PdfView({
controller: this.controller,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
.width('100%')
.height('100%')
}
}
3.3 设置PDF文档预览效果
pdfViewManager为PDF文档提供了丰富的预览特定特性。
- 单双页布局,是否连续滚动和页面适配方式。
- 页面跳转,如上一页,下一页,跳转到指定页。
- 页面放大、缩小。
图1:提供了双页预览布局,页面宽度适配和连续滚动的预览方式
3.3.1 接口说明
接口名 | 描述 |
---|---|
setPageLayout(columnCount: PageLayout): void | 设置页面布局模式。其中“columnCount”取值如下:
|
setPageContinuous(isContinuous: boolean): void | 设置页面滚动是否连续排列。 |
setPageFit(pageFit: PageFit): void | 设置页面的适配模式。 |
goToPage(pageIndex: number): void | 跳转到指定页。 |
setPageZoom(zoom: number): void | 设置视图的缩放比例。 |
3.3.2 示例代码
- 先加载PDF文档。
- 调用PdfView预览组件,渲染显示。
- 在按钮【setPreviewMode】里,调用setPageLayout、setPageContinuous等方法,设置文档预览效果。
- 在按钮【goTopage】里,调用goToPage方法,设置页面跳转。
- 在按钮【zoomPage2】里,调用setPageZoom方法,将页面放大2倍。
import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct PdfPage {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
this.loadResult = await this.controller.loadDocument(filePath);
// 注意:这里刚加载文档,请不要在这里立即设置PDF文档的预览方法。
})()
}
build() {
Column() {
Row() {
// 设置预览方式
Button('setPreviewMode').onClick(() => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
// 单页布局
this.controller.setPageLayout(pdfService.PageLayout.LAYOUT_SINGLE);
// 是否连续滚动预览
this.controller.setPageContinuous(true);
// 适配页的预览方式
this.controller.setPageFit(pdfService.PageFit.FIT_PAGE);
}
})
// 跳转到第11页
Button('goTopage').onClick(() => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
this.controller.goToPage(10);
}
})
// 页面放大2倍
Button('zoomPage2').onClick(() => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
this.controller.setPageZoom(2);
}
})
}
PdfView({
controller: this.controller,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
}
}
3.4 搜索关键字
预览PDF文档时,可以对页面的关键词(英文字符不区分大小写)进行搜索并高亮显示,同时使用setSearchIndex方法高亮显示指定的搜索结果。
使用getSearchIndex方法获取当前高亮的索引,可以使用clearSearch方法清除所有搜索结果。
3.4.1 接口说明
接口名 | 描述 |
---|---|
searchKey(text: string, listener: Callback<number>): void | 搜索文本并返回匹配的总数。 |
3.4.2 示例代码
- 先加载PDF文档。
- 调用PdfView预览组件,渲染显示。
- 在按钮【searchKey】里,调用searchKey方法,搜索指定关键字。
- 上一个、下一个搜索按钮跳转到对应的结果。
- 在按钮【getSearchIndex】里,调用getSearchIndex方法,获取当前的搜索结果索引。
- 在按钮【clearSearch】里,调用clearSearch方法,清除搜索结果。
import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct PdfPage {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
private searchIndex = 0;
private charCount = 0;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
this.loadResult = await this.controller.loadDocument(filePath);
})()
}
build() {
Column() {
Row() {
// 搜索关键字
Button('searchKey').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
this.controller.searchKey('C++', (index: number) => {
this.charCount = index;
hilog.info(0x0000, 'PdfPage', 'searchKey %{public}s!', index + '');
})
}
})
// 上一个
Button('setSearchPrevIndex').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
if(this.searchIndex > 0) {
this.controller.setSearchIndex(--this.searchIndex);
}
}
})
// 下一个
Button('setSearchNextIndex').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
if(this.searchIndex < this.charCount) {
this.controller.setSearchIndex(++this.searchIndex);
}
}
})
// 获取当前页索引
Button('getSearchIndex').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let curSearchIndex = this.controller.getSearchIndex();
hilog.info(0x0000, 'PdfPage', 'curSearchIndex %{public}s!', curSearchIndex + '');
}
})
// 清除搜索文本的高亮
Button('clearSearch').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
this.controller.clearSearch();
}
})
}
PdfView({
controller: this.controller,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
}
}
3.5 高亮显示PDF文档
PDF文档在预览时,可以对页面的矩形区域或文本设置高亮显示,高亮颜色可以自定义。
setHighlightText可以同时高亮多个不同的文本。
3.5.1 接口说明
接口名 | 描述 |
---|---|
setHighlightText(pageIndex: number, textArray: string[], color: number): void | 高亮指定文本。 |
注意
3.5.2 示例代码
- 加载PDF文档。
- 调用PdfView预览组件,渲染显示。
- 在按钮【setHighlightText】里,调用setHighlightText方法,设置单个或多个要高亮的文本。
import { pdfService, PdfView, pdfViewManager } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct PdfPage {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
this.loadResult = await this.controller.loadDocument(filePath);
})()
}
build() {
Column() {
Row() {
// 设置文本的高亮显示风格
Button('setHighlightText').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
this.controller.setHighlightText(0, ['白皮书'], 0xAAF9CC00);
}
})
}
// 加载PdfView组件进行预览
PdfView({
controller: this.controller,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
.width('100%').height('100%')
}
}
3.6 批注
进入批注模式,目前支持高亮、下划线和删除线类型批注。
3.6.1 接口说明
接口名 | 描述 |
---|---|
enableAnnotation(annotationType: SupportedAnnotationType, color?: number): void | 在常用操作之间切换并添加批注。 |
3.6.2 示例代码
- 先加载PDF文档。
- 调用PdfView预览组件,渲染显示。
- 调用enableAnnotation方法,进入批注模式。
import { pdfService, pdfViewManager, PdfView } from '@kit.PDFKit';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct PdfPage {
private pdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
let loadResult: pdfService.ParseResult = await this.pdfController.loadDocument(filePath);
if (pdfService.ParseResult.PARSE_SUCCESS === loadResult) {
// 添加删除线批注
this.pdfController.enableAnnotation(pdfViewManager.SupportedAnnotationType.STRIKETHROUGH, 0xAAEEEEEE);
}
})()
}
build() {
Column() {
// 加载PdfView组件进行预览
PdfView({
controller: this.pdfController,
pageFit: pdfService.PageFit.FIT_WIDTH,
showScroll: true
})
.id('pdfview_app_view')
.layoutWeight(1);
}
}
}
3.7 PDF页面转换为图片
3.7.1 场景介绍
调用getPagePixelMap方法,将指定PDF页面转化为图片。
3.7.2 接口说明
接口名 | 描述 |
---|---|
getPagePixelMap(pageIndex: number, isSync?: boolean): Promise<image.PixelMap> | 获取对应PDF页面的缩略图,使用Promise异步回调。 |
3.7.3 示例代码
- 调用loadDocument方法,加载PDF文档。
- 调用getPagePixelMap方法,获取image.PixelMap对象。
- 将image.PixelMap转化为二进制图片文件并保存。
import { pdfService, pdfViewManager } from '@kit.PDFKit';
import { image } from '@kit.ImageKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct PdfPage {
private controller: pdfViewManager.PdfController = new pdfViewManager.PdfController();
private context = getContext() as common.UIAbilityContext;
private loadResult: pdfService.ParseResult = pdfService.ParseResult.PARSE_ERROR_FORMAT;
aboutToAppear(): void {
// 确保沙箱目录有input.pdf文档
let filePath = this.context.filesDir + '/input.pdf';
(async () => {
this.loadResult = await this.controller.loadDocument(filePath);
})()
}
// 将 pixelMap 转成图片格式
pixelMap2Buffer(pixelMap: image.PixelMap): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
/**
设置打包参数
format:图片打包格式,只支持 jpg 和 webp
quality:JPEG 编码输出图片质量
bufferSize:图片大小,默认 10M
*/
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 }
// 创建ImagePacker实例
const imagePackerApi = image.createImagePacker()
imagePackerApi.packToData(pixelMap, packOpts).then((buffer: ArrayBuffer) => {
resolve(buffer)
}).catch((err: BusinessError) => {
reject()
})
})
}
build() {
Column() {
// 转换为图片并保存到应用沙箱
Button('getPagePixelMap').onClick(async () => {
if (this.loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
let pixmap: image.PixelMap = await this.controller.getPagePixelMap(0, true);
if (!pixmap) {
return
}
const imgBuffer = await this.pixelMap2Buffer(pixmap)
const file =
fs.openSync(this.context.filesDir + `/${Date.now()}.png`, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, imgBuffer);
// 关闭文件
await fs.close(file.fd)
}
})
}
}
}