Skip to content

Instantly share code, notes, and snippets.

@lwlizhe
Last active September 25, 2019 06:34
Show Gist options
  • Select an option

  • Save lwlizhe/2a0ad72a9d9d253e7098fcc9dad111e8 to your computer and use it in GitHub Desktop.

Select an option

Save lwlizhe/2a0ad72a9d9d253e7098fcc9dad111e8 to your computer and use it in GitHub Desktop.
flutter 小说阅读器分页逻辑
/// em…………由于大量文字计算,即Cpu计算,在UI的Isolate会阻塞后续的UI事件(例如跳转,动画啥的),所以采取新建Isolate的方式,这也是flutter中建议的&……
/// 但是目前尴尬的是:
/// 非UI的Isolate不支持UI控件,即下面的textPainter.layout废了……一调用就报错
/// https://github.com/flutter/flutter/issues/30604
/// 所以,理论上来说,这块的计算应该放到一个子线程中,对于目前功能来说,也可以说是isolate中,但是flutter 现在不支持……
/// 现在个人有几种想法:
/// 1、翻页的时候动态计算,只缓存几页的内容,下次翻页的时候再计算
/// 2、https://github.com/flutter/flutter/issues/30604 裁剪canvas
/// 3、平台计算……
/// 4、自己新建一个主isolate?但是不给它任何View?
///
///
/// 评测结果记录:
/// 1、这样不行,这样无法计算上一章的最后一页
/// 2、但是这种方式是基于不自定义段落间距,而固定所有行距实现的,无法自定义
/// 3、但是不能保证Android平台和ios平台自己计算结果和flutter的一致……
/// 4、好像https://pub.dev/packages/flutter_isolate 实现了这点,但是运行不起来,不太清楚具体原因,先看下官方plugin中的android_alarm_manager具体实现方式吧。
static List<ReaderChapterPageContentConfig> getChapterPageContentConfigList(
int targetChapterId,
String content,
double height,
double width,
double fontSize,
double lineSpacing,
double paragraphSpacing,
) {
String tempTotalContent = content;
List<ReaderChapterPageContentConfig> pageConfigList = [];
double currentHeight = 0;
TextPainter textPainter = TextPainter(textDirection: TextDirection.ltr);
while (tempTotalContent.length > 0) {
ReaderChapterPageContentConfig config = ReaderChapterPageContentConfig();
config.paragraphConfigs = [];
config.currentChapterId = targetChapterId;
config.currentContentFontSize = fontSize;
config.currentContentFontSize = fontSize;
config.currentContentLineSpacing = lineSpacing;
config.currentContentParagraphSpacing = paragraphSpacing;
/// 配置段落
ContentParagraphConfig paragraphConfig = ContentParagraphConfig();
paragraphConfig.paragraphLines = [];
List<String> lines = List();
while (currentHeight < height) {
/// 配置画笔 ///
textPainter.text = TextSpan(
text: tempTotalContent, style: TextStyle(fontSize: fontSize));
textPainter.layout(maxWidth: width);
/// 如果最后一行再添一行比页面高度大,或者已经没有内容了,那么当前页面计算结束
if (currentHeight + fontSize + lineSpacing >= height ||
tempTotalContent.length == 0) {
break;
}
/// 单行的偏移量
int endContentSingleLineOffset =
textPainter.getPositionForOffset(Offset(width, 0)).offset;
/// 当前一行的内容
String currentSingleLineContent =
tempTotalContent.substring(0, endContentSingleLineOffset);
/// 重置内容
tempTotalContent = tempTotalContent.substring(
endContentSingleLineOffset, tempTotalContent.length);
lines.add(currentSingleLineContent);
/// 如果行开头是换行符,表示当前段落已经到了结尾,那么将当前段落配置加入到总配置中,并重置内容
if (tempTotalContent.startsWith("\n")) {
/// 如果以换行符开头,那么删除换行符
tempTotalContent =
tempTotalContent.substring(1, tempTotalContent.length);
paragraphConfig.paragraphLines.addAll(lines);
config.paragraphConfigs.add(paragraphConfig);
paragraphConfig = ContentParagraphConfig();
paragraphConfig.paragraphLines = [];
lines = List();
currentHeight += (fontSize + paragraphSpacing);
} else {
/// 改变当前计算高度
currentHeight += (fontSize + lineSpacing);
}
}
if (lines != null && lines.length != 0) {
paragraphConfig.paragraphLines = lines;
config.paragraphConfigs.add(paragraphConfig);
}
pageConfigList.add(config);
currentHeight = 0;
}
return pageConfigList;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment