两页 PDF 并排显示,屏幕上却叠在了一起。再修一次,两页又离得太远。后来页面看着正常了,搜索高亮却和文字对不上了。
![]()
这是作者在开发 MihirakiPDFViewer 时踩的坑。这个应用是给 iPad 用的 PDF 阅读器,专门读自己扫描的书。作者想要两页对开的阅读效果,还希望封面能单独显示。AI 帮着写代码、改代码,但一次修改到底有没有生效,得反复打开 PDF 实际看,还得把预期效果描述得更精确。
作者把这次经历定位成面向初学者的开发复盘,不是完整的 PDF 渲染教程。文中配的示意图用来解释布局问题,不是当时调试的截图。
改布局,得先有个看得见的目标
早期尝试的结果是:页面重叠、页面偏移、页面之间多出不该有的空隙。改一次布局,可能修好一个症状,另一个还留着。代码说修好了,只能当起点,还是得打开 PDF 亲眼确认。
把需求拆成三条之后,事情才清楚起来:
- 保持每一页的宽高比;
- 让两页都落在可用的阅读区域内;
- 让两页的内侧边缘在跨页的中心线上相接。
这里有个容易忽略的区别:页面的容器和页面可见的内容不是一回事。容器可以占掉半块屏幕,而缩放后塞进去的页面比容器窄。把可见页面在容器里居中,书脊附近就会多出一条空隙。
盯着页面的尺寸、缩放比例和位置看,问题才变得具体。光说“把空隙去掉”不够,能说清哪两条边该相接、哪些比例该保持不变,请求才有用。作者最大的收获是:在要求下一次布局修改之前,先把期望看到的画面描述出来。
从右往左读,不只是把顺序反过来
日文书籍让页面顺序成了另一个独立问题。开发期间,一个从右往左的配置打开后停在了最后一页,而不是开头。
作者把这件事拆成三个决定:哪些页面属于同一个跨页;哪一页在左、哪一页在右;哪个跨页最先出现,翻页时又怎么在文档里移动。这三件事互相关联,但把它们一起反过来,并不会自动得到想要的阅读体验。
用一个五页的例子说明,数字是 PDF 文件里的位置,从 1 开始,不是印刷页码。每个方括号表示屏幕从左到右的内容:
- 从左往右、封面不单独显示:[1 | 2] → [3 | 4] → [5]
- 从右往左、封面不单独显示:[2 | 1] → [4 | 3] → [5]
- 从右往左、封面单独显示:[1] → [3 | 2] → [5 | 4]
最终,页面分组被抽成了一个辅助模块 PDFPageGrouping,它只处理页码索引数组,不依赖 PDFKit 对象。这样配对规则就能脱离视图单独检查和测试。
对初学者有用的做法很简单:动手做完整阅读器之前,先用带页码的小例子写下来。五页文档足以把封面规则和左右位置讲清楚。封面不单独显示时,第 5 页没有配对;封面单独显示时,剩下四页组成两个完整的跨页。不过这些例子还是得在真实界面里验证,分组正确不代表初始选中页和翻页行为也正确。
页面一动,搜索高亮也跟着遭殃
另一个问题出现在搜索上:文字找对了,高亮却画错了地方。页面图像按它在跨页里的对齐方式定位,高亮计算却还假设页面是居中的。两套计算单独看都合理,放到屏幕上就对不上。
修法是让图像和高亮共用同一套页面原点计算。这里的原点指页面左上角在屏幕上的位置,共用的辅助函数 alignedPageOriginX 负责给出水平方向的那部分。
这提醒了一件事:页面和它上面的覆盖层属于同一个视觉功能。改完页面位置,除了看页面本身,还得检查搜索结果。这个道理同样适用于图片编辑器、文档查看器以及其他带标注的界面——底层内容一旦移动或缩放,画在它上面的一切都要重新核对。
作者的预期也在日常阅读中变化。比如一开始要求控件出现时页面缩小,用了一阵之后又改了这个要求。有些修改来自发现哪种手感更好,而不是原来的指令没实现。
下一次改布局之前,作者打算先写一段这样的描述:打开一个五页、含可搜索文本的 PDF,用从右往左的跨页模式,封面单独显示。第一屏显示第 1 页,下一个跨页左边是第 3 页、右边是第 2 页。页面保持比例,落在阅读区域内,在中心相接。在任意一页搜索一个词,确认高亮保持对齐。显示再隐藏控件,然后重新检查页面尺寸和位置。
这段描述给了 AI 辅助修改之后可以观察验证的东西,也能把真正的 bug 和“我自己改了主意”区分开。两页视图这件事教给作者的是:把期望看到的东西说得更具体,把页面分组和翻页导航分开,页面几何一变就检查覆盖层。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.