当前位置: 首页 > news >正文

iOS Epub阅读器改造记录

六个月前在这个YHEpubDemo阅读器的基础上做了一些优化,这里做一下记录。

1.首行缩进修复

由于分页的存在,新的一页的首行可能是新的一行,则应该缩进;也可能是前面一页段落的延续,这时候不应该缩进。YHEpubDemo基于XDSReader,XDSReader目前存在新页首行没有缩进的问题。

修复方案如下:

原来预排版分页后将每一页的富文本设置给XDSReadView,这样就失去了排版的连续性。现在改为将整个章节的富文本设置给XDSReadView,并且对该页需要显示的文本范围进行布局。

在XDSReadView.m的reloadView底部加上以下代码:

CGRect rect = UIEdgeInsetsInsetRect(self.readTextView.bounds, self.readTextView.edgeInsets);DTCoreTextLayoutFrame *layoutFrame = [self.readTextView.layouter layoutFrameWithRect:rect range:_pageRange];self.readTextView.layoutFrame = layoutFrame;

因为前面我们已经给readTextView设置了整个章节的富文本:

self.readTextView.attributedString = self.readAttributedContent;

因此我们这里要根据布局区域的大小和布局文本的范围,使用layouter来产生一个layout frame。这样产生的布局是具有连续性的。如果仍然使用原来分页的方式的话,需要判断当前页第一行开始处,是否位于上一页的段落中。如果不在其中,而是新的段落,就要获取上一页段落的样式中的headIndent,将其设置给当前页第一行样式中的firstLineHeadIndent。

2.CSS rem修复

XDSReader基于DTCoreText,DTCoreText有自己的css和HTML解析器,但是不支持css的rem特性,这样会导致字体大小有问题。由于DTCoreText没有提供root element上下文,目前暂时将rem当em处理,虽然会有一些误差,但不至于字体大小变1pt。

3.树形目录

根据epub规范,我们是可以解析获得任意多级的目录的。考虑到目录可以折叠展开,当我们获得了树形数据结构后,我们可以使用BFS(宽度优先遍历)来实现目录的打平:

- (void)reloadData
{self.catalogs = [NSMutableArray arrayWithArray:CURRENT_BOOK_MODEL.catalog.children];NSMutableArray *q = [NSMutableArray arrayWithArray:CURRENT_BOOK_MODEL.catalog.children];while (q.count > 0) {XDSCatalogueModel *top = q[0];[q removeObjectAtIndex:0];if(top.isExpand){[q addObjectsFromArray:top.children];NSInteger idx = [self.catalogs indexOfObject:top];if(idx == NSNotFound){idx = -1;}[self.catalogs insertObjects:top.children atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(idx+1, top.children.count)]];}}[self.tableView reloadData];
}

首先我们将一级目录节点加入临时数组和结果数组,如果当前临时数组数组不为空,则取出第一个,并且从临时数组中移除。如果这个节点是展开的,就把这个节点的子节点加入临时数组。现在我们从结果数组中找到这个节点的位置,将它的子节点按顺序插入后面。像这样往复前面的操作,直到临时数组为空为止。最终我们得到了一个平坦的列表。

4.增加页码

增加页码就是在预排版和分页时,需要记录每一个章节的页码范围,每一页的文字范围等,然后据此计算页面所在的页码,以及页码所在的文字范围等。

5.textblock背景色修复

源码中会给textblock设置一个难看的深蓝色的背景色,在我们的修复中会首先尝试获取textblock的背景色,没有的话才设置为白色:

 CGColorRef color = [textBlock.backgroundColor CGColor];if(!color){color = [[UIColor whiteColor] CGColor];}

6.其他

另外对阅读进度记录,添加note也做了一些修复。增加了水平滚动翻页类型。

最终的效果:

 

 源码:GitHub - Mamong/YHEpubDemo: Epub 阅读器

 后续考虑使用Swift重写,并将epub解析部分抽取出来。

相关文章:

iOS Epub阅读器改造记录

六个月前在这个YHEpubDemo阅读器的基础上做了一些优化,这里做一下记录。 1.首行缩进修复 由于分页的存在,新的一页的首行可能是新的一行,则应该缩进;也可能是前面一页段落的延续,这时候不应该缩进。YHEpubDemo基于XDS…...

负载均衡搭建

LVS-DR部署 [客户端] node1 192.168.157.148 [lvs] node2 192.168.157.142 [web服务器] node3 192.168.157.145 node4 192.168.157.146(1)[lvs] yum install -y ipvsadm.x86_64 配置LVS负载均衡服务 (1)手动添加LVS转发1&#xff…...

form表单input标签的23种type类型值?

当你学了很多技术以后,再回头看来,竟然被一个被一个基础问题虐了,23个类型值说不全,不是少这个,就是少那个,那么23种类型都有什么呢? text 单行文本输入框 password 密码输入框 file …...

python selenium如何保存网站的cookie用于下次自动登录

## 一、python selenium如何保存网站的cookie 使用Selenium保存网站的Cookie非常简单。下面是一个示例,展示了如何使用Selenium打开网站,然后保存获取到的Cookie: from selenium import webdriver# 初始化浏览器 browser webdriver.Chrome…...

DHCP Server

简介 动态主机配置协议 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议) 是 RFC 1541(已被 RFC 2131 取代)定义的标准协议,该协议允许服务器向客户端动态分配 IP 地址和配置信息。 使用UDP协…...

DMR+PoC宽窄融合互通解决方案

当前,Tetra、PDT、DMR、P25等专网通信的主流窄带技术,能够保障在紧急情况下可靠的关键语音通信对讲,但随着行业用户对图片、视频、数据等宽带业务的需求越来越强烈,原本单一的语音通信早已无法满足用户对新需求。 北峰BF-SCP810 D…...

Springboot定时执行任务

定时任务 TaskScheduler 任务调度者 TaskExecutor 任务执行者 EnableScheduling//开启定时功能的注释 Scheduled(cron"* * * * * * *")//什么时候执行~ cron表达式(秒 分 时 日 月 星期 ) Cron表达式 主启动类加上注解开启任务调度 package com.qf.sping09te…...

【Apollo】阿波罗自动驾驶:塑造自动驾驶技术的未来

前言 Apollo (阿波罗)是一个开放的、完整的、安全的平台,将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统,快速搭建一套属于自己的自动驾驶系统。 开放能力、共享资源、加速创新、持续共赢是 Apollo 开放平台的口号。百度把自己所拥有的强大、…...

JavaEE初阶:多线程 - Thread 类的基本用法

上次我们了解了多线程的五种创建方法,今天来学习Thread的基本用法。 目录 run和start Thread常见的构造方法 Thread的几个常见属性 后台线程 是否存活 线程终止 1.使用标志位 2.使用Thread自带的标志 等待线程 run和start 首先需要理解Thread的run和star…...

编写 loading、加密解密 发布NPM依赖包,并实施落地使用

你的 Loading 开箱即可用的 loading, 说明:vue3-loading 是一个方便在 Vue 3 项目中使用的加载指示器组件的 npm 插件。它允许您轻松地在项目中添加加载动画,提升用户体验。 目录 你的 Loading🌍 安装🛹 演示地址&…...

【剑指Offer 57】和为s的连续正数序列,Java解密。

LeetCode 剑指Offer 75道练习题 文章目录 剑指Offer:和为s的连续正数序列示例:限制:解题思路:剑指Offer:和为s的连续正数序列 【题目描述】 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。 序列内的数字由小到大排列,不同序列按照首…...

深度学习实战基础案例——卷积神经网络(CNN)基于SqueezeNet的眼疾识别|第1例

文章目录 前言一、数据准备1.1 数据集介绍1.2 数据集文件结构 二、项目实战2.1 数据标签划分2.2 数据预处理2.3 构建模型2.4 开始训练2.5 结果可视化 三、数据集个体预测 前言 SqueezeNet是一种轻量且高效的CNN模型,它参数比AlexNet少50倍,但模型性能&a…...

麦肯锡发布《2023年度科技报告》!

在经历了 2022 年技术投资和人才的动荡之后,2023 年上半年,人们对技术促进商业和社会进步的潜力重新燃起了热情。生成式人工智能(Generative AI)在这一复兴过程中功不可没,但它只是众多进步中的一个,可以推…...

JAVASE---数组的定义与使用

数组的基本概念 什么是数组 数组是具有相同类型元素的集合,在内存中连续存储。 1. 数组中存放的元素其类型相同 2. 数组的空间是连在一起的 3. 每个空间有自己的编号,起始位置的编号为0,即数组的下标 数组的创建及初始化 数组的创建 T[…...

211、仿真-基于51单片机土壤湿度智能盆栽灌溉报警Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括: 需要完整的资料可以点击下面的名片加下我,找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&am…...

记录TensorRT8.5.0安装

1.下载网址NVIDIA TensorRT 8.x Download | NVIDIA Developer TensorRT不同的版本依赖于不同的cuda版本和cudnn版本。根据自己电脑的cuda版本和cudnn版本来决定要下载哪个TensorRT版本 查看cudnn版本 cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2 cat /usr/l…...

flutter ListView 滚动到最后一个items位置

flutter 想要实现一个listview初始化时和数据变化后显示到列表的最末,简单地说就是像聊天窗或者是日志输出那样的情景。 要在Flutter中实现在初始化时和数据变化后将ListView自动定位到最后一个item的位置,你可以使用ScrollController来控制滚动位置&am…...

WMS:SurfaceView绘制显示

WMS:SurfaceView绘制显示 1、SurfaceView控件使用1.1 Choreographer接受VSync信号1.2 自定义SurfaceView1.3 结果 2、SurfaceView获取画布并显示2.1 SurfaceHolder.lockCanvas()2.2 SurfaceHolder.unlockCanvasAndPost(Canvas canvas) 1、SurfaceView控件使用 1.1 Choreograph…...

【Spring系列篇--关于IOC的详解】

目录 面试经典题目: 1. 什么是spring?你对Spring的理解?简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 2.什么是IoC?你对IoC的理解?IoC的重要性?将实例化对象的权利从程序员…...

__ob__: Observer 后缀的数组的取值方式

开发中,经常从接口、父组件中,拿到数组然后给新的数组使用, 但是,有时候会发现带有 __ob__: Observer 后缀的数组,对这种数组来说,你是无法取到这个数组的值的, 而且,离谱的是consol…...

集团化全员学习企业在线学习平台选型指南|政企专属解决方案

在数字化人才培养浪潮下,集团化全员学习已成为央企、国企、大型上市公司的核心战略,而一款稳定、可管控、高合规的企业在线学习平台,是支撑万人级培训的核心底座。传统分散式培训存在管理混乱、标准不统一、效果不可追溯等痛点,本…...

从RoPE到Retention:一文拆解RetNet如何用‘旋转’和‘衰减’重塑序列建模

RetNet技术解析:如何用旋转与衰减机制突破Transformer的局限 当ChatGPT掀起大语言模型浪潮时,Transformer架构已成为AI领域的基石。然而,其平方级计算复杂度带来的高推理成本,始终是工业界难以回避的痛点。微软与清华大学联合提出…...

龙芯3A5000开发板PMON升级UEFI固件实战指南

1. 项目概述:从“能用”到“好用”的固件升级之路最近折腾了一块搭载龙芯3A5000处理器的开发板,型号是迅为的LS3A5000。拿到手的时候,板子预装的固件还是传统的PMON。PMON对于玩龙芯的老朋友来说不陌生,它功能稳定,但界…...

SaySo 语音识别相关技术解析,从语音输入到可用文本

摘要语音识别正在从一个独立功能,变成越来越多桌面应用里的基础交互能力。对于 SaySo 这类 PC 端语音工具来说,语音识别不仅仅是把声音转成文字,更关键的是如何在桌面工作流中做到识别准确、响应及时、体验稳定。本文将围绕 SaySo 的语音识别…...

机器学习核心术语全解析:从评估指标到TensorFlow实战避坑指南

1. 项目概述与核心价值刚接触机器学习,尤其是像TensorFlow这样庞大框架的朋友,最头疼的莫过于满屏的英文术语。什么“Backpropagation”、“Softmax”、“Embedding”,每个词都认识,但组合在一起就让人云里雾里。更别提那些缩写&a…...

别再为Gurobi学术许可发愁了!手把手教你从申请到激活(附学信网报告攻略)

Gurobi学术许可全流程实战指南:从申请到Python集成 第一次接触Gurobi优化求解器时,我被它强大的性能所吸引,但随即陷入了学术许可申请的迷茫中。和许多研究生同学一样,我在学信网报告下载、邮件沟通、命令行激活等环节屡屡碰壁。本…...

3大突破:AEUX如何重塑设计到动画的无缝工作流

3大突破:AEUX如何重塑设计到动画的无缝工作流 【免费下载链接】AEUX Editable After Effects layers from Sketch artboards 项目地址: https://gitcode.com/gh_mirrors/ae/AEUX 在数字创意领域,设计师们长期面临着一个令人沮丧的现实&#xff1a…...

iOS激活锁终极绕过指南:5分钟免费解锁iPhone完整方案

iOS激活锁终极绕过指南:5分钟免费解锁iPhone完整方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 对于拥有二手iPhone却卡在激活锁界面的用户来说,applera1n提供了一个专业、…...

3大策略掌握Avidemux视频编辑:从源码编译到专业级处理

3大策略掌握Avidemux视频编辑:从源码编译到专业级处理 【免费下载链接】avidemux2 Avidemux2, simple video editor 项目地址: https://gitcode.com/gh_mirrors/avi/avidemux2 Avidemux是一款开源跨平台视频编辑工具,专注于快速剪辑、编码转换和批…...

Kubernetes 监控与可观测性深度解析:Prometheus + Grafana + Loki

Kubernetes 监控与可观测性深度解析:Prometheus Grafana Loki 引言 在云原生环境中,监控与可观测性是保障系统稳定运行的关键。Kubernetes 生态提供了丰富的监控工具,其中 Prometheus、Grafana 和 Loki 组成了完整的可观测性栈。本文将深…...