Skip to content
ComPDF
Guides

创建注释

ComPDF 支持全类型的注释,包括便签,链接,图形,标记,图章,手绘,音频注释等,满足多样的注释需求。

注意: 使用函数CPDFPage.convertRectToPage将Android设备坐标转换为PDF页面坐标;使用函数CPDFPage.convertPointFromPage将PDF页面坐标转换为Android设备坐标

创建便签注释

功能说明

便签注释(Text Annotation)通常以小图标或标签的形式显示在 PDF 页面中。 用户点击该图标后,可展开查看或编辑注释内容。

该注释类型常用于:

  • 添加个人备注或阅读笔记
  • 标记待办事项或提醒信息
  • 在不影响原始 PDF 内容的前提下,补充说明信息

编程创建

适用于无需用户交互、由程序自动生成注释的场景,例如:

  • 批量生成批注
  • 从服务器同步注释数据
  • 文档打开时自动插入注释

创建步骤

  1. 获取目标页对应的 CPDFPage 对象
  2. 在页面上创建便签注释(TEXT 类型)
  3. 设置注释的外观和内容属性
  4. 更新注释外观,使其渲染到页面中
java
// 目标页码
int pageIndex = 0;

// 获取页面对象
CPDFPage page = document.pageAtIndex(pageIndex);

// 创建便签注释
CPDFTextAnnotation textAnnotation =
        (CPDFTextAnnotation) page.addAnnot(CPDFAnnotation.Type.TEXT);

// 获取页面尺寸
RectF pageSize = page.getSize();

// 设置注释初始位置(页面坐标)
RectF insertRect = new RectF(0, 0, 50, 50);
insertRect = page.convertRectToPage(
        false,
        pageSize.width(),
        pageSize.height(),
        insertRect
);

// 设置注释属性
textAnnotation.setColor(Color.RED);
textAnnotation.setAlpha(255);
textAnnotation.setRect(insertRect);
textAnnotation.setContent("ComPDF");

// 更新注释外观
textAnnotation.updateAp();
kotlin
// 目标页码
val pageIndex = 0

// 获取页面对象
val page = document.pageAtIndex(pageIndex)

// 创建便签注释
val textAnnotation =
    page.addAnnot(CPDFAnnotation.Type.TEXT) as CPDFTextAnnotation

// 获取页面尺寸
val pageSize = page.size

// 坐标转换
val insertRect = page.convertRectToPage(
    false,
    pageSize.width(),
    pageSize.height(),
    RectF(0f, 0f, 50f, 50f)
)

// 设置注释属性
textAnnotation.setColor(Color.RED)
textAnnotation.alpha = 255
textAnnotation.rect = insertRect
textAnnotation.content = "ComPDF"

// 更新注释外观
textAnnotation.updateAp()

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView =
        (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(textAnnotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(textAnnotation, isFocused)
}

交互创建

适用于 用户手动点击 PDF 页面添加便签注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击页面即可创建便签,并可通过弹窗编辑注释内容。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加便签注释的触摸模式
  3. 用户点击 PDF 页面区域,创建便签注释
  4. 弹出自定义编辑弹窗输入内容
  5. 保存或删除注释后,退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加便签注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.TEXT);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);

弹出自定义编辑弹窗

为了在屏幕中直接弹出编辑便签内容,需要继承 CPDFTextAnnotAttachHelper 并重写 onAddTextAnnot 方法,实现自定义弹窗逻辑:

java
public class CustomTextAnnotAttachHelper extends CPDFTextAnnotAttachHelper {
    @Override
    protected void onAddTextAnnot(CPDFTextAnnotImpl cpdfTextAnnot) {
        cpdfTextAnnot.setFocused(true);

        // 创建自定义编辑弹窗
        CNoteEditDialog editDialog = CNoteEditDialog.newInstance("");
        editDialog.setDismissListener(() -> {
            String content = editDialog.getContent();
            cpdfTextAnnot.onGetAnnotation().setContent(content);
        });

        editDialog.setSaveListener(v -> {
            // 保存便签内容
            String content = editDialog.getContent();
            cpdfTextAnnot.onGetAnnotation().setContent(content);
            editDialog.dismiss();
            pageView.setFocusAnnot(cpdfTextAnnot);

            // 退出注释模式
            readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);
            readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
        });

        editDialog.setDeleteListener(v -> {
            // 删除便签注释
            pageView.deleteAnnotation(cpdfTextAnnot);
            editDialog.dismiss();
        });

        FragmentActivity fragmentActivity = CViewUtils.getFragmentActivity(readerView.getContext());
        if (fragmentActivity != null) {
            editDialog.show(fragmentActivity.getSupportFragmentManager(), "noteEditDialog");
        }
    }
}

注册自定义便签注释辅助类

java
// 完成注册后,当用户通过交互方式添加便签注释时,**会直接弹出自定义弹窗编辑内容**。
cpdfReaderView
    .getAnnotImplRegistry()
    .registAttachHelper(CPDFTextAnnotation.class, CustomTextAnnotAttachHelper.class);

需要点击便签注释弹出编辑弹窗请继承 CPDFTextAnnotImpl.java 进行实现

java
cpdfReaderView.getAnnotImplRegistry().registImpl(CPDFTextAnnotation.class, CPDFtextAnnotImpl.class);

创建链接注释

链接注释使用户能够直接跳转到文档中的其他位置或外部资源,提供更丰富的导航体验。

编程创建

创建链接注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页面上创建链接注释对象。
  3. 通过CPDFDestination设置链接跳转到第2页。
  4. 设置注释属性,并将CPDFDestination对象附加到注释上。

创建链接的代码如下:

java
// 插入页码。
int pageNumber = 0;
// 获取pdf的页面实例。
CPDFPage page = document.pageAtIndex(pageNumber);
CPDFLinkAnnotation linkAnnotation = (CPDFLinkAnnotation) page.addAnnot(CPDFAnnotation.Type.LINK);
RectF pageSize = page.getSize();
RectF insertRect = new RectF(0,0,100,100);
// 坐标转换。
insertRect = page.convertRectToPage(false , pageSize.width(), pageSize.height(), insertRect);
linkAnnotation.setRect(insertRect);

// 跳转到指定页码
CPDFGoToAction goToAction = new CPDFGoToAction();
CPDFDestination destination = new CPDFDestination(pageNumber,0,pageSize.height(),1f);
goToAction.setDestination(document, destination);
linkAnnotation.setLinkAction(goToAction);

// 打开指定网页
CPDFUriAction uriAction = new CPDFUriAction();
uriAction.setUri("website");
linkAnnotation.setLinkAction(uriAction);
// 将注释更新到文档上。
linkAnnotation.updateAp();
kotlin
// 插入页码。
val pageNumber = 0
// 获取pdf的页面实例。
val page = document.pageAtIndex(pageNumber)
val linkAnnotation = page.addAnnot(CPDFAnnotation.Type.LINK) as CPDFLinkAnnotation
val pageSize = page.size
// 坐标转换。
linkAnnotation.rect = run {
  var insertRect: RectF? = RectF(0F, 0F, 100F, 100F)
  page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect)
}

// 跳转到指定页码
linkAnnotation.linkAction = CPDFGoToAction().apply {
  setDestination(document,  CPDFDestination(pageNumber, 0F, pageSize.height(), 1F))
}

// 打开指定网页
linkAnnotation.linkAction = CPDFUriAction().apply { 
  uri = "website"
}
linkAnnotation.updateAp()

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView =
        (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户手动点击 PDF 页面添加链接注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户在PDF页面中获取矩形,并可通过弹出弹窗编辑注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加链接注释的触摸模式
  3. 用户滑取 PDF 页面区域,创建链接注释
  4. 弹出自定义编辑弹窗输入内容
  5. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加链接注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.Link);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);

弹出自定义编辑弹窗

为了在屏幕中直接弹出设置链接注释内容,需要继承 CPDFLinkAnnotAttachHelper 并重写 setLinkAction 方法,实现自定义弹窗逻辑:

java
public class CLinkAnnotAttachHelper extends CPDFLinkAnnotAttachHelper {

    @Override
    public void setLinkAction(CPDFLinkAnnotation linkAnnotation) {
        super.setLinkAction(linkAnnotation);
        if (linkAnnotation == null || !linkAnnotation.isValid()) return;

        // 创建并显示编辑弹窗
        CActionEditDialogFragment editDialog = CActionEditDialogFragment.newInstance(
                readerView.getPDFDocument().getPageCount()
        );

        editDialog.setOnLinkInfoChangeListener(new CActionEditDialogFragment.COnActionInfoChangeListener() {
            @Override
            public void cancel() {
                // 取消时删除注释
                pageView.deleteAnnotation(linkAnnotation);
            }

            @Override
            public void createWebsiteLink(String url) {
                // 绑定链接到注释
                CPDFUriAction action = new CPDFUriAction();
                action.setUri(url);
                linkAnnotation.setLinkAction(action);
                pageView.addAnnotation(linkAnnotation, false);
            }

            @Override
            public void createEmailLink(String email) {
                CPDFUriAction action = new CPDFUriAction();
                action.setUri(email);
                linkAnnotation.setLinkAction(action);
                pageView.addAnnotation(linkAnnotation, false);
            }

            @Override
            public void createPageLink(int page) {
                CPDFGoToAction action = new CPDFGoToAction();
                CPDFDestination dest = new CPDFDestination(page - 1, 0f,
                        readerView.getPDFDocument().pageAtIndex(page - 1).getSize().height(), 1f);
                action.setDestination(readerView.getPDFDocument(), dest);
                linkAnnotation.setLinkAction(action);
                pageView.addAnnotation(linkAnnotation, false);
            }
        });

        FragmentActivity activity = CViewUtils.getFragmentActivity(readerView.getContext());
        if (activity != null) {
            editDialog.show(activity.getSupportFragmentManager(), "linkDialog");
        }
    }
}
kotlin
class CLinkAnnotAttachHelper : CPDFLinkAnnotAttachHelper() {

    override fun setLinkAction(linkAnnotation: CPDFLinkAnnotation?) {
        super.setLinkAction(linkAnnotation)
        if (linkAnnotation == null || !linkAnnotation.isValid) return

        // 创建并显示编辑弹窗
        val editDialog = CActionEditDialogFragment.newInstance(
            readerView.pdfDocument.pageCount
        )

        editDialog.setOnLinkInfoChangeListener(object : CActionEditDialogFragment.COnActionInfoChangeListener {
            override fun cancel() {
                // 取消时删除注释
                pageView?.deleteAnnotation(linkAnnotation)
            }

            override fun createWebsiteLink(url: String) {
                // 绑定网站链接到注释
                val action = CPDFUriAction().apply { this.uri = url }
                linkAnnotation.linkAction = action
                pageView?.addAnnotation(linkAnnotation, false)
            }

            override fun createEmailLink(email: String) {
                // 绑定邮箱链接到注释
                val action = CPDFUriAction().apply { this.uri = email }
                linkAnnotation.linkAction = action
                pageView?.addAnnotation(linkAnnotation, false)
            }

            override fun createPageLink(page: Int) {
                val action = CPDFGoToAction()
                val document = readerView.pdfDocument
                val height = document.pageAtIndex(page - 1).size.height()
                val destination = CPDFDestination(page - 1, 0f, height, 1f)
                action.setDestination(document, destination)
                linkAnnotation.linkAction = action
                pageView?.addAnnotation(linkAnnotation, false)
            }
        })

        // 获取 FragmentActivity 并显示弹窗
        CViewUtils.getFragmentActivity(readerView.context)?.let { activity ->
            editDialog.show(activity.supportFragmentManager, "linkDialog")
        }
    }
}

注册自定义链接注释辅助类

java
// 完成注册后,当用户通过交互方式添加便签注释时,**会直接弹出自定义弹窗编辑内容**。
cpdfReaderView
    .getAnnotImplRegistry()
    .registAttachHelper(CPDFLinkAnnotation.class, CLinkAnnotAttachHelper.class);

创建文本注释

文本注释允许用户在 PDF 文档中插入自由格式的文字,用于添加注解、评论或解释文档内容。

编程创建

创建文本注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页面上创建文本注释对象。
  3. 设置注释属性。
  4. 更新注释外观使其显示在文档上。

创建文本注释的代码如下:

java
// 插入页码。
int pageNumber = 0;
// 获取pdf的页面实例。
CPDFPage page = document.pageAtIndex(pageNumber);
CPDFFreetextAnnotation freetextAnnotation = (CPDFFreetextAnnotation) page.addAnnot(CPDFAnnotation.Type.FREETEXT);
RectF pageSize = page.getSize();
RectF insertRect = new RectF(0F,0F,100F,100F);
// 坐标转换。
insertRect = page.convertRectToPage(false,pageSize.width(),pageSize.height(),insertRect);
freetextAnnotation.setRect(insertRect);
// 设置注释属性。
freetextAnnotation.setContent("ComPDF Samples");
freetextAnnotation.setFreetextAlignment(CPDFFreetextAnnotation.Alignment.ALIGNMENT_CENTER);
CPDFTextAttribute textAttribute = new CPDFTextAttribute(CPDFTextAttribute.FontNameHelper.obtainFontName(
  CPDFTextAttribute.FontNameHelper.FontType.Helvetica, false, false
), 12, Color.RED);
freetextAnnotation.setFreetextDa(textAttribute);
// 将注释更新到文档上。
freetextAnnotation.updateAp();
kotlin
val page = document.pageAtIndex(0)
(page.addAnnot(CPDFAnnotation.Type.FREETEXT) as CPDFFreetextAnnotation).apply {
  // 坐标转换。
	val size = page.size
  rect = page.convertRectToPage(false, size.width(), size.height(),  RectF(0f, 0f, 100f, 100f))
  // 设置注释属性。
  freetextAlignment = CPDFFreetextAnnotation.Alignment.ALIGNMENT_CENTER
  freetextDa = CPDFTextAttribute(CPDFTextAttribute.FontNameHelper.obtainFontName(
    CPDFTextAttribute.FontNameHelper.FontType.Courier, false, false
  ), 12f, Color.RED)
  alpha = 255
  content = "ComPDF Samples"
  // 将注释更新到文档上。
  updateAp()
}

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView =
        (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户点击PDF页面区域添加文本注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击PDF页面中任意位置创建文本注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加文本注释的触摸模式
  3. 用户点击 PDF 页面区域,创建文本注释输入框
  4. 弹出软键盘输入内容
  5. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加链接注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.FREETEXT);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);

创建图形注释

图形注释包括矩形、圆形、线条和箭头等形状,用于在文档中绘制图形以突出或标记特定区域,表达文字不易描述的信息。

编程创建

创建图形注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页面上依次创建矩形,圆形,线段注释对象。
  3. 设置注释属性。
  4. 依次更新注释外观使其显示在文档上。

创建图形注释的代码如下:

java
// 插入页码。
int pageNumber = 0;
// 获取pdf的页面实例。
CPDFPage page = document.pageAtIndex(pageNumber);

// 在该页面上创建矩形释对象。
CPDFSquareAnnotation squareAnnotation = (CPDFSquareAnnotation) page.addAnnot(CPDFAnnotation.Type.SQUARE);
RectF pageSize = page.getSize();
RectF insertRect = new RectF(0,0,100,100);
// 坐标转换。
insertRect = page.convertRectToPage(false,pageSize.width(),pageSize.height(),insertRect);
squareAnnotation.setRect(insertRect);
// 设置注释属性。
squareAnnotation.setBorderColor(Color.YELLOW);
CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8.0F, 0F});
squareAnnotation.setBorderStyle(borderStyle);
squareAnnotation.setBorderAlpha(255);
squareAnnotation.setFillColor(Color.RED);
squareAnnotation.setFillAlpha(255);
// 将注释更新到文档上。
squareAnnotation.updateAp();

// 在该页面上创建圆形注释对象。
CPDFCircleAnnotation circleAnnotation = (CPDFCircleAnnotation) page.addAnnot(CPDFAnnotation.Type.CIRCLE);
RectF pageSize = page.getSize();
RectF insertRect = new RectF(0,0,100,100);
// 坐标转换。
insertRect = page.convertRectToPage(false,pageSize.width(),pageSize.height(),insertRect);
circleAnnotation.setRect(insertRect);
// 设置注释属性。
circleAnnotation.setBorderColor(Color.YELLOW);
CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8.0F, 0F});
circleAnnotation.setBorderStyle(borderStyle);
circleAnnotation.setBorderAlpha(255);
circleAnnotation.setFillColor(Color.RED);
circleAnnotation.setFillAlpha(255);
// 将注释更新到文档上。
circleAnnotation.updateAp();

// 在该页面上创建线段注释对象。
CPDFLineAnnotation lineAnnotation = (CPDFLineAnnotation) page.addAnnot(CPDFAnnotation.Type.LINE);
float lineWidth = 10f;
RectF pageSize = page.getSize();
// 坐标转换。
PointF startPoint = new PointF(0,0);
PointF endPoint = new PointF(200,200);
RectF area = new RectF();
area.left = Math.min(startPoint.x, endPoint.x);
area.right = Math.max(startPoint.x, endPoint.x);
area.top = Math.min(startPoint.y, endPoint.y);
area.bottom = Math.max(startPoint.y, endPoint.y);
area.left -= lineWidth * 2;
area.top -= lineWidth * 2;
area.right += lineWidth * 2;
area.bottom += lineWidth * 2;
area.set(page.convertRectToPage(false, pageSize.width(), pageSize.height(), area));
startPoint.set(page.convertPointToPage(false, pageSize.width(), pageSize.height(), startPoint));
endPoint.set(page.convertPointToPage(false, pageSize.width(), pageSize.height(), endPoint));
lineAnnotation.setRect(area);
lineAnnotation.setLinePoints(startPoint, endPoint);
// 设置注释属性。
lineAnnotation.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_ARROW);
CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid,lineWidth,null);
lineAnnotation.setBorderStyle(borderStyle);
lineAnnotation.setBorderWidth(10F);
lineAnnotation.setBorderAlpha(255);
lineAnnotation.setBorderColor(Color.RED);
// 将注释更新到文档上。
lineAnnptation.updateAp();
kotlin
// 插入页码。
val pageNumber = 0
// 获取pdf的页面实例。
val page = document.pageAtIndex(pageNumber)

// 在该页面上创建矩形释对象。
val squareAnnotation = page.addAnnot(CPDFAnnotation.Type.SQUARE) as CPDFSquareAnnotation
val pageSize = page.size
// 坐标转换。
squareAnnotation.rect = page.convertRectToPage(false, pageSize.width(), pageSize.height(), RectF(0F, 0F, 100F, 100F))

squareAnnotation.apply {
  // 设置注释属性。
  borderColor = Color.YELLOW
  borderStyle = CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10F, floatArrayOf(8F, 0F))
  borderAlpha = 255
  fillColor = Color.RED
  fillAlpha = 255
}
// 将注释更新到文档上。
squareAnnotation.updateAp()

// 在该页面上创建圆形注释对象。
val circleAnnotation = page.addAnnot(CPDFAnnotation.Type.CIRCLE) as CPDFCircleAnnotation
val pageSize = page.size
// 坐标转换。
circleAnnotation.rect = page.convertRectToPage(false, pageSize.width(), pageSize.height(), RectF(0F, 0F, 100F, 100F))
// 设置注释属性。
circleAnnotation.borderColor = Color.YELLOW
circleAnnotation.borderStyle = CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10F, floatArrayOf(8F, 0F))
circleAnnotation.borderAlpha = 255
circleAnnotation.fillColor = Color.RED
circleAnnotation.fillAlpha = 255
// 将注释更新到文档上。
circleAnnotation.updateAp()

// 在该页面上创建线段注释对象。
val lineAnnotation = page.addAnnot(CPDFAnnotation.Type.LINE) as CPDFLineAnnotation
val lineWidth = 10F
val pageSize = page.size
val startPoint = PointF(0F, 0F)
val endPoint = PointF(200F, 200F)

val area = RectF().apply {
  left = min(startPoint.x, endPoint.x) - lineWidth * 2
  top = min(startPoint.y, endPoint.y) - lineWidth * 2
  right = max(startPoint.x, endPoint.x) + lineWidth * 2
  bottom = max(startPoint.y, endPoint.y) + lineWidth * 2
  set(page.convertRectToPage(false, pageSize.width(), pageSize.height(), this))
}
// 坐标转换。
listOf(startPoint, endPoint).forEach { point ->
  point.set(page.convertPointToPage(
    false,
    pageSize.width(),
    pageSize.height(),
    point))
}
// 设置注释属性。
lineAnnotation.rect = area
lineAnnotation.setLinePoints(startPoint, endPoint)
lineAnnotation.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_ARROW)
lineAnnotation.borderStyle = CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, lineWidth, null)
lineAnnotation.borderAlpha = 255
lineAnnotation.borderColor = Color.RED
// 将注释更新到文档上。
lineAnnotation.updateAp();

线段注释类型枚举

名称描述
LINETYPE_UNKNOWN非标准或无效的线段端点。
LINETYPE_NONE没有线段端点。
LINETYPE_ARROW两条短线以尖锐的角度相交,形成一个开放的箭头。
LINETYPE_CLOSEDARROW两条短线以尖锐的角度相交,就像样式一样,并通过第三条线连接,形成一个三角形闭合的箭头,内部填充了注释的内部颜色。
LINETYPE_SQUARE一个填充有注释内部颜色的正方形。
LINETYPE_CIRCLE一个填充有注释内部颜色的圆形。
LINETYPE_DIAMOND一个填充有注释内部颜色的菱形形状。
LINETYPE_BUTT一条与线本身垂直的短线,位于端点上。
LINETYPE_ROPENARROW两条与相反方向的短线。
LINETYPE_RCLOSEDARROW一个与相反方向的三角形闭合箭头。
LINETYPE_SLASH一条短线,位于端点上,大约比与线本身垂直的方向顺时针旋转30度。

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView = (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户点击PDF页面区域添加图形注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击PDF页面中任意位置创建图形注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加图形注释的触摸模式
  3. 用户滑取 PDF 页面区域,创建图形注释
  4. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加链接注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
// SQUARE, CIRCLE, LINE
readerView.setCurrentFocusedType(CPDFAnnotation.Type.SQUARE);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);

创建标记注释

在 PDF 文档中添加标记,以突出、强调或说明特定内容,例如重要的段落、行或单词、关键词或表格等。ComPDF 提供高亮,下划线,波浪线,删除线四种标记注释。

代码创建

创建标记注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 通过页面对象创建文本对象。
  3. 使用该文本对象取得需要添加标记的文本位置。
  4. 在该页面上创建对应的标记对象。
  5. 设置标记对象的属性。
  6. 更新注释外观使其显示在文档上。

以高亮注释为例,创建标记注释的代码如下:

java
// 首先,从页面上的特定区域获取TextSelection数组,选择文本。
CPDFPage pdfPage = document.pageAtIndex(0);
RectF size = pdfPage.getSize();

CPDFTextPage pdfTextPage = pdfPage.getTextPage();
RectF selectRect = new RectF(0f, 0f, 500f, 500f);

selectRect = pdfPage.convertRectFromPage(false, size.width(), size.height(), selectRect);
CPDFTextSelection[] textSelectionArr = pdfTextPage.getSelectionsByLineForRect(selectRect);

// 然后,为特定区域添加高亮显示注释。
RectF annotRect = new RectF();
CPDFHighlightAnnotation highlightAnnotation = (CPDFHighlightAnnotation) pdfPage.addAnnot(CPDFAnnotation.Type.HIGHLIGHT);
highlightAnnotation.setColor(Color.YELLOW);
highlightAnnotation.setAlpha((255 / 4));
RectF[] quadRects = new RectF[textSelectionArr.length];
StringBuilder markedTextSb = new StringBuilder();
int len = textSelectionArr.length;
for (int i = 0; i < len; i++) {
  CPDFTextSelection textSelection = textSelectionArr[i];
  if (textSelection == null) {
    continue;
  }
  RectF rect = new RectF(textSelection.getRectF());
  if (annotRect.isEmpty()) {
    annotRect.set(rect);
  } else {
    annotRect.union(rect);
  }

  quadRects[i] = new RectF(textSelection.getRectF());
  String text = pdfTextPage.getText(textSelection.getTextRange());
  if (!TextUtils.isEmpty(text)) {
    markedTextSb.append(text);
  }
}

highlightAnnotation.setQuadRects(quadRects);
highlightAnnotation.setMarkedText(markedTextSb.toString());
highlightAnnotation.setRect(annotRect);
highlightAnnotation.updateAp();
kotlin
// 首先,从页面上的特定区域获取TextSelection数组,选择文本。
val page = document.pageAtIndex(0)

val size = page.size
val pdfTextPage = page.textPage
val selectRect = RectF(0f, 0f, 500f, 500f)
val convertedRect = page.convertRectFromPage(false, size.width(), size.height(), selectRect)
val textSelectionArr = pdfTextPage.getSelectionsByLineForRect(convertedRect)

val highlightAnnotation = page.addAnnot(CPDFAnnotation.Type.HIGHLIGHT) as CPDFHighlightAnnotation
highlightAnnotation.color = Color.YELLOW
highlightAnnotation.alpha = 255 / 4

val quadRects = mutableListOf<RectF>()
val markedTextSb = StringBuilder()

val quadRects = mutableListOf<RectF>()
val markedTextSb = StringBuilder()
// 然后,为特定区域添加高亮显示注释。
val annotRect = RectF()

textSelectionArr.forEach { textSelection ->
    textSelection?.let {
        val rect = RectF(it.rectF)
        if (annotRect.isEmpty) {
            annotRect.set(rect)
        } else {
            annotRect.union(rect)
        }
        quadRects.add(RectF(it.rectF))
        val text = pdfTextPage.getText(it.textRange)
        if (!TextUtils.isEmpty(text)) {
            markedTextSb.append(text)
        }
    }
}

highlightAnnotation.quadRects = quadRects.toTypedArray()
highlightAnnotation.markedText = markedTextSb.toString()
highlightAnnotation.rect = annotRect
highlightAnnotation.updateAp()

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView = (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户点击PDF页面区域添加标记注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击PDF页面中任意位置创建标记注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加标记注释的触摸模式
  3. 用户滑取 PDF 页面文本区域,创建标记注释
  4. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加链接注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
// HIGHLIGHT, UNDERLINE, STRIKEOUT, SQUIGGLY
readerView.setCurrentFocusedType(Type.HIGHLIGHT);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);

创建图章注释

图章注释用于标识和验证文档的来源和真实性,ComPDF 支持标准图章,文字图章,图像图章。

编程创建

创建图章注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页面上创建对应的图章。
  3. 设置图章属性。
  4. 更新注释外观使其显示在文档上。

创建图章注释的代码如下:

java
// 获取需要创建注释的页面对象。
int pageNumber = 0;
CPDFPage page = document.pageAtIndex(pageNumber);

// 创建标准印章。
CPDFStampAnnotation standardStamp = (CPDFStampAnnotation)page.addAnnot(CPDFAnnotation.Type.STAMP);
standardStamp.setStandardStamp(CPDFStampAnnotation.StandardStamp.COMPLETED);
RectF pageSize = page.getSize();
RectF insertRect = standardStamp.getRect();
insertRect.set(page.convertRectFromPage(false, pageSize.width(), pageSize.height(), insertRect));
float defaultWidth = 200f;
PointF vertex = new PointF(0,0);
insertRect.set(vertex.x, vertex.y, vertex.x + defaultWidth, vertex.y + defaultWidth * Math.abs(insertRect.height() / insertRect.width()));
standardStamp.setRect(page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect));
standardStamp.updateAp();

// 创建文字印章。
CPDFStampAnnotation textStamp = (CPDFStampAnnotation) page.addAnnot(CPDFAnnotation.Type.STAMP);
textStamp.setTextStamp(new CPDFStampAnnotation.TextStamp("Hello world","2022/01/01 12:00:00", CPDFStampAnnotation.TextStampShape.TEXTSTAMP_RIGHT_TRIANGLE.id, CPDFStampAnnotation.TextStampColor.TEXTSTAMP_GREEN.id));
RectF pageSize = page.getSize();
RectF insertRect = textStamp.getRect();
insertRect.set(page.convertRectFromPage(false, pageSize.width(), pageSize.height(), insertRect));
float defaultWidth = 200F;
PointF vertex = new PointF(0,0);
insertRect.set(vertex.x, vertex.y, vertex.x + defaultWidth, vertex.y + defaultWidth * Math.abs(insertRect.height() / insertRect.width()));
textStamp.setRect(page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect));
textStamp.updateAp();

// 创建图片印章。
CPDFStampAnnotation imageStamp = (CPDFStampAnnotation) page.addAnnot(CPDFAnnotation.Type.STAMP);
String imagePath = "imagePath";
float defaultWidth = 200F;
PointF vertex = new PointF(0,0);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
RectF insertRect = new RectF(vertex.x, vertex.y, vertex.x + defaultWidth, vertex.y + defaultWidth * options.outHeight / options.outWidth);
RectF pageSize =page.getSize();
insertRect.set(page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect));
imageStamp.setRect(insertRect);

if (imagePath.endsWith("png")){
  BitmapFactory.Options tmpOptions = new BitmapFactory.Options();
  tmpOptions.inMutable = true;
  Bitmap bitmap = BitmapFactory.decodeFile(imagePath, tmpOptions);
  imageStamp.updateApWithBitmap(bitmap);
  bitmap.recycle();
}else {
  imageStamp.setImageStamp(imagePath);
  imageStamp.updateAp();
}
kotlin
// 获取需要创建注释的页面对象。
val pageNumber = 0
val page = document.pageAtIndex(pageNumber)

// 创建标准印章。
val standardStamp = page.addAnnot(CPDFAnnotation.Type.STAMP) as CPDFStampAnnotation
standardStamp.setStandardStamp(CPDFStampAnnotation.StandardStamp.COMPLETED)
val pageSize = page.size
val insertRect = standardStamp.rect
insertRect.set(
  page.convertRectFromPage(false, pageSize.width(), pageSize.height(), insertRect)
)
val defaultWidth = 200F
val vertex = PointF(0f, 0F)
insertRect.set(
  vertex.x,
  vertex.y,
  vertex.x + defaultWidth,
  vertex.y + defaultWidth * kotlin.math.abs(insertRect.height() / insertRect.width())
)
standardStamp.rect = page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect)
standardStamp.updateAp()


// 创建文字印章。
val textStamp = page.addAnnot(CPDFAnnotation.Type.STAMP) as CPDFStampAnnotation
textStamp.textStamp = CPDFStampAnnotation.TextStamp(
  "Hello world",
  "2022/01/01 12:00:00",
  CPDFStampAnnotation.TextStampShape.TEXTSTAMP_RIGHT_TRIANGLE.id,
  CPDFStampAnnotation.TextStampColor.TEXTSTAMP_GREEN.id
)
val textStampInsertRect = textStamp.rect
textStampInsertRect.set(
  page.convertRectFromPage(false, pageSize.width(), pageSize.height(), textStampInsertRect)
)
textStampInsertRect.set(
  vertex.x,
  vertex.y,
  vertex.x + defaultWidth,
  vertex.y + defaultWidth * kotlin.math.abs(textStampInsertRect.height() / textStampInsertRect.width())
)
textStamp.rect = page.convertRectToPage(false, pageSize.width(), pageSize.height(), textStampInsertRect)
textStamp.updateAp()

// 创建图片印章。
val imageStamp = page.addAnnot(CPDFAnnotation.Type.STAMP) as CPDFStampAnnotation
val imagePath = "imagePath"
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(imagePath, options)
val imageStampInsertRect = RectF(
  vertex.x,
  vertex.y,
  vertex.x + defaultWidth,
  vertex.y + defaultWidth * options.outHeight / options.outWidth
)
imageStamp.rect = page.convertRectToPage(false, pageSize.width(), pageSize.height(), imageStampInsertRect)

if (imagePath.endsWith("png")) {
  val tmpOptions = BitmapFactory.Options()
  tmpOptions.inMutable = true
  val bitmap = BitmapFactory.decodeFile(imagePath, tmpOptions)
  imageStamp.updateApWithBitmap(bitmap)
  bitmap.recycle()
} else {
  imageStamp.setImageStamp(imagePath)
  imageStamp.updateAp()
}

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView = (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户点击PDF页面区域添加图章注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击PDF页面中任意位置创建图章注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加图章注释的触摸模式
  3. 用户点击 PDF 页面,创建图章注释
  4. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加图章注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
// 设置标准图章、文字图章或图像图章
readerView.setCurrentFocusedType(Type.STAMP);

// 3. 设置要添加的标准图章或图片
CPDFAnnotAttribute attribute = readerView.getReaderAttribute().getAnnotAttribute();
CPDFStampAttr stampAttr = attribute.getStampAttr();
// 标准图章
stampAttr.setStandardStamp(CPDFStampAnnotation.StandardStamp.ACCEPTED);
// 文字图章
stampAttr.setTextStamp(params.getTextStamp());
// 图片图章
stampAttr.setImagePath(params.getImagePath(), false);
// 经过以上步骤,点击PDF页面区域即可完成添加对应的图章注释

// 4. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);
kotlin
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT)

// 2. 启用添加图章注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT)
// 设置标准图章、文字图章或图像图章
readerView.setCurrentFocusedType(Type.STAMP)
// 3. 设置要添加的标准图章或图片
let attribute = readerView.getReaderAttribute().getAnnotAttribute()
let stampAttr = attribute.getStampAttr()
// 标准图章
stampAttr.setStandardStamp(CPDFStampAnnotation.StandardStamp.ACCEPTED)
// 文字图章
stampAttr.setTextStamp(params.getTextStamp())
// 图片图章
stampAttr.setImagePath(params.getImagePath(), false)
// 经过以上步骤,点击PDF页面区域即可完成添加对应的图章注释

// 4. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE)
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN)

创建手绘注释

手绘注释直接快捷,用于直接绘制标注。

代码创建

创建手绘注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页面上创建手绘注释。
  3. 设置手绘注释经过的路径。
  4. 设置注释其他属性。
  5. 更新注释外观使其显示在文档上。

创建手绘注释的代码如下:

java
// 获取需要创建注释的页面对象。
int pageNumber = 0;
CPDFPage page = document.pageAtIndex(pageNumber);
// 设置手绘注释经过的路径。
ArrayList<ArrayList<PointF>> mDrawing = new ArrayList<>();
ArrayList<PointF> arc1 = new ArrayList<>();
arc1.add(new PointF(0,0));
arc1.add(new PointF(10,10));
arc1.add(new PointF(20,20));
mDrawing.add(arc1);
ArrayList<PointF> arc2 = new ArrayList<>();
arc2.add(new PointF(5,5));
arc2.add(new PointF(15,15));
arc2.add(new PointF(25,25));
mDrawing.add(arc2);
// 在该页面上创建手绘注释。
CPDFInkAnnotation inkAnnotation = (CPDFInkAnnotation) page.addAnnot(CPDFInkAnnotation.Type.INK);
float scaleValue = 1;
inkAnnotation.setColor(Color.BLUE);
inkAnnotation.setAlpha(255);
inkAnnotation.setBorderWidth(10 / scaleValue);
RectF rect = null;
RectF size = page.getSize();
if (size.isEmpty()) {
  return;
}
int lineCount = mDrawing.size();
PointF[][] path = new PointF[lineCount][];
for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
  ArrayList<PointF> line = mDrawing.get(lineIndex);
  int pointCount = line.size();
  PointF[] linePath = new PointF[pointCount];
  for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
    PointF point = line.get(pointIndex);
      /****** 计算路径所包围的最小矩形 ******/
    if (rect == null) {
      rect = new RectF(point.x, point.y, point.x, point.y);
    } else {
      rect.union(point.x, point.y);
    }
      /****** 计算转换为页面并存储在linePath集合中的坐标点 ******/
    linePath[pointIndex] = (page.convertPointToPage(false, size.width(), size.height(), point));
  }
  path[lineIndex] = linePath;
}
float dx = 10 / scaleValue / 2;
rect.inset(-dx, -dx);
rect.set(page.convertRectToPage(false, size.width(), size.height(), rect));
inkAnnotation.setInkPath(path);
inkAnnotation.setRect(rect);
inkAnnotation.updateAp();
kotlin
// 获取需要创建注释的页面对象。
val pageNumber = 0
val page = document.pageAtIndex(pageNumber)
// 设置手绘注释经过的路径。
val mDrawing = mutableListOf<MutableList<PointF>>()
val arc1 = mutableListOf(PointF(0f, 0f), PointF(10f, 10f), PointF(20f, 20f))
mDrawing.add(arc1)
val arc2 = mutableListOf(PointF(5f, 5f), PointF(15f, 15f), PointF(25f, 25f))
mDrawing.add(arc2)
// 在该页面上创建手绘注释。
val inkAnnotation = page.addAnnot(CPDFAnnotation.Type.INK) as CPDFInkAnnotation
val scaleValue = 1
inkAnnotation.color = Color.BLUE
inkAnnotation.alpha = 255
inkAnnotation.borderWidth = 10F / scaleValue

var rect: RectF? = null
val size = page.size
if (size.isEmpty) {
  return
}
val lineCount = mDrawing.size
val path = Array(lineCount) { emptyArray<PointF>() }
for (lineIndex in 0 until lineCount) {
  val line = mDrawing[lineIndex]
  val pointCount = line.size
  val linePath = Array(pointCount) { PointF() }
  for (pointIndex in 0 until pointCount) {
    val point = line[pointIndex]
    // 计算路径所包围的最小矩形。
    if (rect == null) {
      rect = RectF(point.x, point.y, point.x, point.y)
    } else {
      rect.union(point.x, point.y)
    }
    // 计算转换为页面并存储在linePath集合中的坐标点。
    linePath[pointIndex] = page.convertPointToPage(
      false,
      size.width(),
      size.height(),
      point
    )
  }
  path[lineIndex] = linePath
}
val dx = 10F / scaleValue / 2
rect?.inset(-dx, -dx)
rect?.set(page.convertRectToPage(false, size.width(), size.height(), rect))
inkAnnotation.inkPath = path
inkAnnotation.rect = rect
inkAnnotation.updateAp()

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView = (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户绘制PDF页面区域创建手绘注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户通过触摸并拖动手指在PDF页面上自由绘制来创建手绘注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加手绘注释的触摸模式
  3. 用户在 PDF 页面上绘制,创建手绘注释
  4. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加手绘注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
readerView.setCurrentFocusedType(Type.INK);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);
kotlin
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT)

// 2. 启用添加手绘注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT)
readerView.setCurrentFocusedType(Type.INK)

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE)
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN)

辅助类

我们还提供了一系列的API帮助您在交互模式中更好的创建手绘注释

java
// 获取当前 ReaderView 的手写绘制辅助类
CPDFReaderView.TInkDrawHelper inkDrawHelper = readerView.getInkDrawHelper();

// 设置绘制模式为橡皮擦模式(用于擦除手写内容)
inkDrawHelper.setMode(IInkDrawCallback.Mode.ERASE);

// 设置绘制模式为绘制模式(用于手写绘制)
inkDrawHelper.setMode(IInkDrawCallback.Mode.DRAW);

// 清除当前页面上所有手写绘制内容
inkDrawHelper.clearInkOperation();

// 检查是否可以重做(redo)上一步操作
boolean canRedo = inkDrawHelper.canRedo();

// 检查是否可以撤销(undo)上一步操作
boolean canUndo = inkDrawHelper.canUndo();

// 保存当前手写绘制状态到文档
inkDrawHelper.onSave();

// 撤销上一步手写绘制操作
inkDrawHelper.onUndo();

// 重做上一步被撤销的手写绘制操作
inkDrawHelper.onRedo();
kotlin
// 获取当前 ReaderView 的手写绘制辅助类
val inkDrawHelper = readerView.inkDrawHelper

// 设置绘制模式为橡皮擦(用于擦除已绘制内容)
inkDrawHelper.setMode(IInkDrawCallback.Mode.ERASE)

// 设置绘制模式为绘制模式(用于手写绘制)
inkDrawHelper.setMode(IInkDrawCallback.Mode.DRAW)

// 清除当前页面上所有手写绘制内容
inkDrawHelper.clearInkOperation()

// 检查是否可以重做(redo)上一步操作
val canRedo = inkDrawHelper.canRedo()

// 检查是否可以撤销(undo)上一步操作
val canUndo = inkDrawHelper.canUndo()

// 保存当前手写绘制状态到文档
inkDrawHelper.onSave()

// 撤销上一步手写绘制操作
inkDrawHelper.onUndo()

// 重做上一步被撤销的手写绘制操作
inkDrawHelper.onRedo()

创建音频注释

代码创建

创建音频注释的步骤如下:

  1. 获取需要创建注释的页面对象。
  2. 在该页上创建音频注释。
  3. 设置音频文件。
  4. 设置其他属性。
  5. 更新注释外观使其显示在文档上。

创建音频注释的代码如下:

java
// 获取需要创建注释的页面对象。
CPDFPage page = document.pageAtIndex(0);
CPDFSoundAnnotation soundAnnotation = (CPDFSoundAnnotation) page.addAnnot(CPDFAnnotation.Type.SOUND);
RectF insertRect = new RectF(50, 300, 100, 350);
RectF size = page.getSize();
insertRect =  page.convertRectToPage(false, size.width(), size.height(), insertRect);
soundAnnotation.setRect(insertRect);
soundAnnotation.setSoundPath(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "Bird.wav"));
soundAnnotation.updateAp();
kotlin
// 获取需要创建注释的页面对象。
val page = document.pageAtIndex(0)
val soundAnnotation = page.addAnnot(CPDFAnnotation.Type.SOUND) as CPDFSoundAnnotation
var insertRect = RectF(50F, 300F, 100F, 350F)
val size = page.size
insertRect = page.convertRectToPage(false, size.width(), size.height(), insertRect)
soundAnnotation.rect = insertRect
soundAnnotation.setSoundPath(getAssetsTempFile(context(), "Bird.wav"))
soundAnnotation.updateAp()

ReaderView 同步

如果当前 PDF 正在通过 CPDFReaderView 显示,并且目标页已加载或正在屏幕中显示, 需要将注释同步添加到对应的 CPDFPageView 中,才能立即显示在界面上。

仅已显示或即将显示的页面才会存在 CPDFPageView,请务必判空。

java
CPDFPageView pageView = (CPDFPageView) readerView.getChild(pageIndex);

if (pageView != null) {
    boolean isFocused = false;
    pageView.addAnnotation(annotation, isFocused);
}
kotlin
val pageView = readerView.getChild(pageIndex) as? CPDFPageView

pageView?.let {
    val isFocused = false
    it.addAnnotation(annotation, isFocused)
}

交互创建

适用于 用户点击PDF页面区域添加音频注释 的场景,常见于阅读或编辑模式。 在这种模式下,用户点击PDF页面中任意位置创建音频注释。

操作流程

  1. 切换 CPDFReaderView 至注释模式
  2. 启用添加音频注释的触摸模式
  3. 用户点击 PDF 页面,创建音频注释
  4. 退出注释模式

示例代码:

java
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT);

// 2. 启用添加音频注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT);
readerView.setCurrentFocusedType(Type.SOUND);

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE);
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN);
kotlin
// 1. 进入注释模式
readerView.setViewMode(CPDFReaderView.ViewMode.ANNOT)

// 2. 启用添加音频注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.ADD_ANNOT)
readerView.setCurrentFocusedType(Type.SOUND)

// 3. 退出注释模式
readerView.setTouchMode(CPDFReaderView.TouchMode.BROWSE)
readerView.setCurrentFocusedType(CPDFAnnotation.Type.UNKNOWN)