likes
comments
collection
share

想要用RN写个小说APP第三天【文章分页📚】

作者站长头像
站长
· 阅读数 59

在某天某时,我立下了这个奇怪的flag,关于我和他的爱恨情仇,请看我的第一篇文章 想要用RN写个小说APP第一天 当前已经实现的功能有:

  • 爬取页面内容
  • 状态管理以及数据持久化
  • 小说内容主题自定义(字体/颜色/...)
  • 爬取后如何进行文本分页✅
  • 分页后如何在用户阅读时,无感加载上/下一章
  • (相关的bug经历我最近都会写出来🧐🧐🧐) 项目地址,star看我后续更新🌠🌠🌠

今日内容

如何准确的得到当前页面能够显示的页面内容

第一次构思

今天的内容是我写这个APP目前遇到的第二痛苦的功能(第一是无感加载分章)。自己看小说时,就这样一页一页的翻过去,甚至在我开始做这个功能之前。也没有察觉到一个大难题已经挡在了我面前。当我信心满满的敲下:

const Content:React.FC = () =>{
    return <View>....???.</View>
}

下一刻...?我该怎么办,将全部小说章节内容文本渲染到页面后,怎么把文本换成多页?我承认我抓瞎了。无从下手,这个的唯一难点就是,在一串连续的的文本中,我该如何知道当前页面能够填充的字符数,将其准确的截断。经过自己的简单思考后,一个粗略的想法出来了:通过字体大小(fontSzie)计算屏幕宽度一行能够容纳的字数,再通过屏幕高度除以行高,得到一页能够显示的文本总行数,最后相乘得到一页可以显示的字数。有了这个想法,我真的下手如有神,写下了这样一段代码:

export default function Test({content}: {content: string}) {
  const fontSize = 30,
    lineHeight = 50;
  const width = useWindowDimensions().width;
  const height = useWindowDimensions().height;
  const count = (width / fontSize) * (height / lineHeight);
  return (
    <View>
      {[0, 1, 2, 3, 4, 5].map(_ => (
        <Text style={{padding: 30, fontSize: 80}}>
          {content.slice(_ * count, _ * count + count)}
        </Text>
      ))}
    </View>
  );
}

显而易见的,这样确实有点效果,但他是失败的~~~~ ,他大概可以分出对应页数,这个是对的,但是每一页的内容中,都有着较大的缺口才能够填满整个页面,显示出来大概是这样的:

想要用RN写个小说APP第三天【文章分页📚】

在红框部分,大概还需要一行半的内容才能填满屏幕,经过一阵折腾过后,我发现了大概的原因,同一fontSize下标点符号数字以及英文字母与汉字的宽度并不相同。然后我就.....

二次重构

发动了我的搜索技能,在gathub以及搜索引擎的帮助下,我拿到了大概这样的一段代码,他的功能以及逻辑大概是这样的:

将一个中文汉字定义为宽度2 英文大写字母是1.1(大概的数值,具体忘了) 英文小写字母是0.9(大概的数值,具体忘了) 各种标点符号定义的范围是(1,1.5) 经过这样的定义后,首先还是要算出一行能够容纳的汉字额个数,得到的字数*2(因为上面我们将汉字宽度定义为数值2) 下一步:定义一个行内容数组,从头遍历文章内容,每一次获取到的字符都要通过上面的方法得到定义的长度,对字符串长度相加的结果(要加上下一次要加上的字符长度)与一行可容纳的长度进行对比,当结果是大于时,说明再加上下一个字符就会超出当前行了,这时候将之前的字符串截取出存入数组,再重复上面的过程,就等到了了一个由文章每一行内容的字符串数组,再计算得到一页可存入的函数,截取行数据数组。再进行遍历显示。 这个方法的显示效果很好的,大概如下:

想要用RN写个小说APP第三天【文章分页📚】

中间插曲

能够写到这,说明上面的方案还是有问题的。上面的方案并非我初次搜寻就得到的,我先是得到了,一篇文章,他的内容是关于起点小说是如何在浏览器中将小说进行水平分页的。文章的重点就是就是一个CSS属性:columns,这个属性能够将一个元素的内容,在给定元素高度中将内容进行分块显示。犹如旱田遇甘露🚿🚿🚿。我立马去试了这个方案,然后得到了....是的,react-native并不支持这个CSS属性。

想要用RN写个小说APP第三天【文章分页📚】

问题

上面的统计长度的方案中,我试了很多个章节都发现有着较好的显示效果,但我一阵开心过后。我突然有个想法,将内容的字体换成我平时最常用的~这也是我由喜转悲的开始。但我经过一整折腾过后,按下键盘的R键(RN的开发工具通过这个控制应用Reload),当页面出来时,我的心凉了一半,大概是这样的:

想要用RN写个小说APP第三天【文章分页📚】

**每一行的内容都不能完美的填满,经过一系列调试,发现了一个让人难受的结果,换了字体之后。每一个汉字以及标点符号的的长度比例都变了....经过了我一段时间的挣扎。最终我放弃了这个方案: **

最终方案

当我想要说服自己放弃水平滑动,而变成更容易实现的垂直滑动,我在RN的Text组件文档中注意到了这样的一个字眼。

想要用RN写个小说APP第三天【文章分页📚】

然后我有又在下面的类型定义中看到了

想要用RN写个小说APP第三天【文章分页📚】

文本行数组,看到这个两个词凑在一起时,我虎躯一震。立刻去测试了我的想法。最终我在Text组件的回调事件onTextLayout中,我得到了lines数组,然后取出数组中的text

onTextLayout={({nativeEvent}) => {
           console.log(nativeEvent.lines);
}}>

想要用RN写个小说APP第三天【文章分页📚】

想要用RN写个小说APP第三天【文章分页📚】

他的结构形式跟前面的方案是一样的,都是将每一行容纳的文本进行分割,但这次是由ReactNative底层进行过一次布局之后再传出给我们。通过之前得到的每页可容纳行数,进行切割得到总页数。而我用于获取布局数组的Text,则使用绝对定位absolute以及可见度opacity设置为0,将其隐藏起来(事了拂衣去,深藏功与名)

  noPlay: {
    pointerEvents: 'none',
    position: 'absolute',
    left: 0,
    top: 0,
    opacity: 0,
  },

结语

分页的这个功能断断续续的卡了我三天。但最终实现的时候,还是感觉我掉的头发是值得的🦳。

这次滴内容就写到这了,后续计划更新(打勾的已经更新了)的内容有: (下面计划的功能都是已经大致完成了💨)

项目地址,star看我后续更新🌠🌠🌠

转载自:https://juejin.cn/post/7158827044350984206
评论
请登录