閱讀器的分頁實現
阿新 • • 發佈:2019-01-10
最近在寫一個閱讀器app,命名為Light,程式碼已經開源,點選檢視Light原始碼。
本專案基於Flutter,瞭解更多請點選flutter.io。
本方案的核心原理是利用了TextPainter特性,通過多次渲染來找到當前頁面能夠顯示的最大字元數。
文字描述:獲得一段內容後呼叫TextPainter.layout(),如果發生行溢位則減少字元數量,如果未溢位則增加字元數量,不斷迴圈這個過程,直到這些字元恰好能夠填滿整個頁面且不溢位,那麼就完成了一次分頁計算。以防萬一,對迴圈設定一個次數上限。
程式流程圖如下:
/// 獲取帶樣式的文字物件
TextSpan getTextSpan(String text ) {
return new TextSpan(text: text, style: _textStyle);
}
/// 接收內容
/// 追加內容返回false
/// 計算完畢返回true
bool load(String text) {
if (layout(text)) {
return false;
}
int start = 0;
int end = text.length;
int mid = (end + start) ~/ 2;
// 最多迴圈20次
for (int i = 0; i < 20; i++) {
if (layout(text.substring(0, mid))) {
if (mid <= start || mid >= end) break;
// 未越界
start = mid;
mid = (start + end) ~/ 2;
} else {
// 越界
end = mid;
mid = (start + end) ~/ 2;
}
}
length = mid;
return true;
}
/// 計算待繪製文字
/// 未超出邊界返回true
/// 超出邊界返回false
bool layout(String text) {
times++;
text = text ?? '';
textPainter
..text = getTextSpan(text)
..layout(maxWidth: pageSize.width);
return !didExceed;
}
/// 是否超出邊界
bool get didExceed {
return textPainter.didExceedMaxLines ||
textPainter.size.height > pageSize.height;
}
完成一次計算的平均時間為23毫秒,在閱讀時幾乎感覺不到卡頓,但是對於整書的分頁計算來說還是很耗時。
如果有問題歡迎即時交流,期待您更精彩的方案。