如何在Android Studio中通过barteksc的Android PdfViewer访问PDF目录
解决barteksc Android PdfViewer获取PDF目录的问题
barteksc的Android PdfViewer底层依赖PdfiumAndroid,控制台打印的目录其实是PDF的大纲(Bookmark/Outline),但库本身没有直接暴露获取大纲的API,需要通过PdfiumCore的原生方法来解析:
实现步骤
1. 确认依赖配置
如果尚未添加相关依赖,在项目的build.gradle中加入:
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1' // 或直接依赖Pdfium核心库 implementation 'com.github.barteksc:piumcore:1.9.0'
2. 读取Assets中的PDF并解析大纲
直接使用PdfiumCore打开Assets内的PDF文件,通过递归遍历大纲节点提取目录信息:
import com.shockwave.pdfium.PdfDocument; import com.shockwave.pdfium.PdfiumCore; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; // 在Activity/Fragment中实现 private List<DirectoryItem> directoryList = new ArrayList<>(); private void loadPdfDirectory() { PdfiumCore pdfiumCore = new PdfiumCore(this); try { // 打开Assets中的目标PDF InputStream inputStream = getAssets().open("target_file.pdf"); PdfDocument pdfDocument = pdfiumCore.newDocument(inputStream); // 获取大纲根节点 PdfDocument.Bookmark rootBookmark = pdfiumCore.getBookmarks(pdfDocument); // 遍历所有大纲节点,收集目录数据 traverseBookmarks(rootBookmark); // 关闭文档释放资源 pdfiumCore.closeDocument(pdfDocument); } catch (IOException e) { e.printStackTrace(); } } // 递归遍历大纲节点 private void traverseBookmarks(PdfDocument.Bookmark bookmark) { if (bookmark == null) return; // 提取标题和页码(Pdfium返回的pageIdx是0索引,转成用户习惯的1-based) String chapterTitle = bookmark.getTitle(); int displayPage = bookmark.getPageIdx() + 1; // 将目录项存入集合 directoryList.add(new DirectoryItem(chapterTitle, displayPage)); // 遍历子目录节点 for (PdfDocument.Bookmark child : bookmark.getChildren()) { traverseBookmarks(child); } } // 自定义数据类存储目录项 public static class DirectoryItem { public String title; public int page; public DirectoryItem(String title, int page) { this.title = title; this.page = page; } }
3. 关键注意事项
- 页码转换:Pdfium返回的
pageIdx是0起始索引,需加1才能和控制台显示的1-based页码一致; - 资源释放:必须调用
pdfiumCore.closeDocument()关闭文档,避免内存泄漏; - 异常处理:需捕获IO异常,处理文件读取失败的场景。
替代方案(不推荐)
如果已经通过PdfView加载了PDF,也可以通过反射获取内部的PdfDocument实例,但该方式依赖库的内部实现,存在版本兼容风险:
import com.shockwave.pdfium.PdfDocument; import com.shockwave.pdfium.PdfiumCore; import java.lang.reflect.Field; private void getDirectoryFromLoadedPdfView(PdfView pdfView) { try { Field mPdfDocumentField = pdfView.getClass().getDeclaredField("mPdfDocument"); mPdfDocumentField.setAccessible(true); PdfDocument pdfDocument = (PdfDocument) mPdfDocumentField.get(pdfView); PdfiumCore pdfiumCore = new PdfiumCore(this); PdfDocument.Bookmark rootBookmark = pdfiumCore.getBookmarks(pdfDocument); traverseBookmarks(rootBookmark); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } }
内容的提问来源于stack exchange,提问作者Shani74
相关产品推荐
相关产品推荐

