mirror of
https://github.com/gedoor/legado.git
synced 2024-07-06 23:47:49 +08:00
优化
This commit is contained in:
parent
16b3efcdb7
commit
952fc96574
@ -2,6 +2,7 @@ package io.legado.app.constant
|
||||
|
||||
import androidx.annotation.IntDef
|
||||
|
||||
@Suppress("ConstPropertyName")
|
||||
object PageAnim {
|
||||
|
||||
const val coverPageAnim = 0
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.legado.app.model
|
||||
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.constant.PageAnim.scrollPageAnim
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.data.entities.Book
|
||||
import io.legado.app.data.entities.BookChapter
|
||||
@ -32,6 +33,7 @@ import kotlinx.coroutines.cancelChildren
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import splitties.init.appCtx
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
@ -241,7 +243,6 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
callBack?.upMenuView()
|
||||
AppLog.putDebug("moveToNextChapter-curPageChanged()")
|
||||
curPageChanged()
|
||||
curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it, upContent) }
|
||||
return true
|
||||
} else {
|
||||
AppLog.putDebug("跳转下一章失败,没有下一章")
|
||||
@ -271,7 +272,6 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
saveRead()
|
||||
callBack?.upMenuView()
|
||||
curPageChanged()
|
||||
curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it, upContent) }
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -321,7 +321,7 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
*/
|
||||
private fun curPageChanged(pageChanged: Boolean = false) {
|
||||
callBack?.pageChanged()
|
||||
if (BaseReadAloudService.isRun) {
|
||||
if (BaseReadAloudService.isRun && isLayoutAvailable) {
|
||||
val scrollPageAnim = pageAnim() == 3
|
||||
if (scrollPageAnim && pageChanged) {
|
||||
ReadAloud.pause(appCtx)
|
||||
@ -350,6 +350,13 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
return curTextChapter?.getPageIndexByCharIndex(durChapterPos) ?: durChapterPos
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否排版到了当前阅读位置
|
||||
*/
|
||||
val isLayoutAvailable inline get() = durPageIndex >= 0
|
||||
|
||||
val isScroll inline get() = pageAnim() == scrollPageAnim
|
||||
|
||||
/**
|
||||
* chapterOnDur: 0为当前页,1为下一页,-1为上一页
|
||||
*/
|
||||
@ -522,7 +529,8 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
.getContent(book, chapter, content, includeTitle = false)
|
||||
val textChapter =
|
||||
ChapterProvider.getTextChapterAsync(chapter, displayTitle, contents, chapterSize)
|
||||
when (val offset = chapter.index - durChapterIndex) {
|
||||
val offset = chapter.index - durChapterIndex
|
||||
when (offset) {
|
||||
0 -> {
|
||||
curTextChapter?.cancelLayout()
|
||||
curTextChapter = textChapter
|
||||
@ -530,44 +538,83 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
callBack?.resetPageOffset()
|
||||
}
|
||||
callBack?.upMenuView()
|
||||
curPageChanged()
|
||||
callBack?.contentLoadFinish()
|
||||
callBack?.onCurrentTextChapterChanged(textChapter, upContent)
|
||||
textChapter.setProgressListener(object : LayoutProgressListener {
|
||||
var available = false
|
||||
|
||||
override fun onLayoutPageCompleted(index: Int, page: TextPage) {
|
||||
if (!available && page.containPos(durChapterPos)) {
|
||||
curPageChanged()
|
||||
callBack?.contentLoadFinish()
|
||||
if (upContent) {
|
||||
callBack?.upContent(offset, resetPageOffset)
|
||||
}
|
||||
available = true
|
||||
}
|
||||
if (upContent && isScroll) {
|
||||
val pageIndex = durPageIndex
|
||||
if (max(index - 3, 0) < pageIndex) {
|
||||
callBack?.upContent(offset, resetPageOffset)
|
||||
}
|
||||
}
|
||||
callBack?.onLayoutPageCompleted(index, page)
|
||||
}
|
||||
|
||||
override fun onLayoutCompleted() {
|
||||
if (upContent) callBack?.upContent(offset, resetPageOffset)
|
||||
success?.invoke()
|
||||
callBack?.onLayoutCompleted()
|
||||
}
|
||||
|
||||
override fun onLayoutException(e: Throwable) {
|
||||
AppLog.put("ChapterProvider ERROR", e)
|
||||
appCtx.toastOnUi("ChapterProvider ERROR:\n${e.stackTraceStr}")
|
||||
callBack?.onLayoutException(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
-1 -> {
|
||||
prevTextChapter?.cancelLayout()
|
||||
prevTextChapter = textChapter
|
||||
if (upContent) {
|
||||
textChapter.setProgressListener(object : LayoutProgressListener {
|
||||
override fun onLayoutCompleted() {
|
||||
callBack?.upContent(offset, resetPageOffset)
|
||||
}
|
||||
})
|
||||
}
|
||||
textChapter.setProgressListener(object : LayoutProgressListener {
|
||||
override fun onLayoutCompleted() {
|
||||
if (upContent) callBack?.upContent(offset, resetPageOffset)
|
||||
success?.invoke()
|
||||
}
|
||||
|
||||
override fun onLayoutException(e: Throwable) {
|
||||
AppLog.put("ChapterProvider ERROR", e)
|
||||
appCtx.toastOnUi("ChapterProvider ERROR:\n${e.stackTraceStr}")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
1 -> {
|
||||
nextTextChapter?.cancelLayout()
|
||||
nextTextChapter = textChapter
|
||||
if (upContent) {
|
||||
textChapter.setProgressListener(object : LayoutProgressListener {
|
||||
override fun onLayoutPageCompleted(index: Int, page: TextPage) {
|
||||
if (index > 1) {
|
||||
return
|
||||
}
|
||||
callBack?.upContent(offset, resetPageOffset)
|
||||
textChapter.setProgressListener(object : LayoutProgressListener {
|
||||
override fun onLayoutPageCompleted(index: Int, page: TextPage) {
|
||||
if (index > 1) {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
if (upContent) callBack?.upContent(offset, resetPageOffset)
|
||||
}
|
||||
|
||||
override fun onLayoutCompleted() {
|
||||
success?.invoke()
|
||||
}
|
||||
|
||||
override fun onLayoutException(e: Throwable) {
|
||||
AppLog.put("ChapterProvider ERROR", e)
|
||||
appCtx.toastOnUi("ChapterProvider ERROR:\n${e.stackTraceStr}")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
textChapter.createLayout(this@ReadBook, book, contents)
|
||||
}.onError {
|
||||
AppLog.put("ChapterProvider ERROR", it)
|
||||
appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}")
|
||||
}.onSuccess {
|
||||
success?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
@ -679,7 +726,7 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
curTextChapter?.cancelLayout()
|
||||
}
|
||||
|
||||
interface CallBack {
|
||||
interface CallBack : LayoutProgressListener {
|
||||
fun upMenuView()
|
||||
|
||||
fun loadChapterList(book: Book)
|
||||
@ -698,8 +745,6 @@ object ReadBook : CoroutineScope by MainScope() {
|
||||
|
||||
fun notifyBookChanged()
|
||||
|
||||
fun onCurrentTextChapterChanged(textChapter: TextChapter, upContent: Boolean = true)
|
||||
|
||||
fun resetPageOffset()
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,6 @@ import io.legado.app.ui.book.read.config.TipConfigDialog.Companion.TIP_DIVIDER_C
|
||||
import io.legado.app.ui.book.read.page.ContentTextView
|
||||
import io.legado.app.ui.book.read.page.ReadView
|
||||
import io.legado.app.ui.book.read.page.entities.PageDirection
|
||||
import io.legado.app.ui.book.read.page.entities.TextChapter
|
||||
import io.legado.app.ui.book.read.page.entities.TextPage
|
||||
import io.legado.app.ui.book.read.page.provider.ChapterProvider
|
||||
import io.legado.app.ui.book.read.page.provider.LayoutProgressListener
|
||||
@ -115,7 +114,6 @@ import io.legado.app.utils.observeEvent
|
||||
import io.legado.app.utils.observeEventSticky
|
||||
import io.legado.app.utils.postEvent
|
||||
import io.legado.app.utils.showDialogFragment
|
||||
import io.legado.app.utils.stackTraceStr
|
||||
import io.legado.app.utils.startActivity
|
||||
import io.legado.app.utils.sysScreenOffTime
|
||||
import io.legado.app.utils.throttle
|
||||
@ -126,7 +124,6 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* 阅读界面
|
||||
@ -1373,47 +1370,11 @@ class ReadBookActivity : BaseReadBookActivity(),
|
||||
binding.readView.autoPager.resume()
|
||||
}
|
||||
|
||||
override fun onCurrentTextChapterChanged(textChapter: TextChapter, upContent: Boolean) {
|
||||
this.upContent = upContent
|
||||
textChapter.setProgressListener(this)
|
||||
}
|
||||
|
||||
override fun onLayoutPageCompleted(index: Int, page: TextPage) {
|
||||
upSeekBarThrottle.invoke()
|
||||
if (upContent) {
|
||||
val durChapterPos = ReadBook.durChapterPos
|
||||
if (page.containPos(durChapterPos)) {
|
||||
runOnUiThread {
|
||||
binding.readView.upContent(0, resetPageOffset = false)
|
||||
}
|
||||
}
|
||||
if (isScroll) {
|
||||
val pageIndex = ReadBook.durPageIndex
|
||||
if (max(index - 3, 0) < pageIndex) {
|
||||
runOnUiThread {
|
||||
binding.readView.upContent(0, resetPageOffset = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.readView.onLayoutPageCompleted(index, page)
|
||||
}
|
||||
|
||||
override fun onLayoutCompleted() {
|
||||
if (upContent) {
|
||||
runOnUiThread {
|
||||
binding.readView.upContent(0, resetPageOffset = false)
|
||||
}
|
||||
}
|
||||
binding.readView.onLayoutCompleted()
|
||||
}
|
||||
|
||||
override fun onLayoutException(e: Throwable) {
|
||||
AppLog.put("ChapterProvider ERROR", e)
|
||||
toastOnUi("ChapterProvider ERROR:\n${e.stackTraceStr}")
|
||||
binding.readView.onLayoutException(e)
|
||||
}
|
||||
|
||||
override fun resetPageOffset() {
|
||||
binding.readView.resetPageOffset()
|
||||
}
|
||||
|
@ -96,8 +96,7 @@ data class TextChapter(
|
||||
}
|
||||
|
||||
fun isLastIndexCurrent(index: Int): Boolean {
|
||||
// 未完成排版时,最后一页是正在排版中的,需要去掉
|
||||
return index >= if (isCompleted) pages.size - 1 else pages.size - 2
|
||||
return index >= pages.size - 1
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,16 +211,12 @@ data class TextChapter(
|
||||
if (pageSize == 0) {
|
||||
return -1
|
||||
}
|
||||
val size = if (isCompleted) pageSize else pageSize - 1
|
||||
val bIndex = pages.fastBinarySearchBy(charIndex, 0, size) {
|
||||
val bIndex = pages.fastBinarySearchBy(charIndex, 0, pageSize) {
|
||||
it.lines.first().chapterPosition
|
||||
}
|
||||
val index = abs(bIndex + 1) - 1
|
||||
if (index == -1) {
|
||||
return -1
|
||||
}
|
||||
// 判断是否已经排版到 charIndex ,没有则返回 -1
|
||||
if (!isCompleted && index == size - 1) {
|
||||
if (!isCompleted && index == pageSize - 1) {
|
||||
val page = pages[index]
|
||||
val line = page.lines.first()
|
||||
val pageEndPos = line.chapterPosition + page.charSize
|
||||
|
@ -67,6 +67,8 @@ class TextChapterLayout(
|
||||
private val indentCharWidth = ChapterProvider.indentCharWidth
|
||||
private val stringBuilder = StringBuilder()
|
||||
|
||||
private var pendingTextPage = TextPage()
|
||||
|
||||
private var isCompleted = false
|
||||
private val job: Coroutine<*>
|
||||
private val bookChapter inline get() = textChapter.chapter
|
||||
@ -167,7 +169,6 @@ class TextChapterLayout(
|
||||
val contents = bookContent.textList
|
||||
var absStartX = paddingLeft
|
||||
var durY = 0f
|
||||
textPages.add(TextPage())
|
||||
if (ReadBookConfig.titleMode != 2 || bookChapter.isVolume) {
|
||||
//标题非隐藏
|
||||
displayTitle.splitNotBlank("\n").forEach { text ->
|
||||
@ -185,7 +186,7 @@ class TextChapterLayout(
|
||||
durY = it.second
|
||||
}
|
||||
}
|
||||
textPages.last().lines.last().isParagraphEnd = true
|
||||
pendingTextPage.lines.last().isParagraphEnd = true
|
||||
stringBuilder.append("\n")
|
||||
durY += titleBottomSpacing
|
||||
}
|
||||
@ -244,7 +245,6 @@ class TextChapterLayout(
|
||||
matcher.group(1)!!,
|
||||
absStartX,
|
||||
durY,
|
||||
textPages,
|
||||
contentPaintTextHeight,
|
||||
stringBuilder,
|
||||
book.getImageStyle()
|
||||
@ -270,10 +270,11 @@ class TextChapterLayout(
|
||||
}
|
||||
}
|
||||
}
|
||||
textPages.last().lines.last().isParagraphEnd = true
|
||||
pendingTextPage.lines.last().isParagraphEnd = true
|
||||
stringBuilder.append("\n")
|
||||
}
|
||||
val textPage = textPages.last()
|
||||
textPages.add(pendingTextPage)
|
||||
val textPage = pendingTextPage
|
||||
val endPadding = 20.dpToPx()
|
||||
val durYPadding = durY + endPadding
|
||||
if (textPage.height < durYPadding) {
|
||||
@ -295,7 +296,6 @@ class TextChapterLayout(
|
||||
src: String,
|
||||
x: Int,
|
||||
y: Float,
|
||||
textPages: ArrayList<TextPage>,
|
||||
textHeight: Float,
|
||||
stringBuilder: StringBuilder,
|
||||
imageStyle: String?,
|
||||
@ -305,15 +305,16 @@ class TextChapterLayout(
|
||||
val size = ImageProvider.getImageSize(book, src, ReadBook.bookSource)
|
||||
if (size.width > 0 && size.height > 0) {
|
||||
if (durY > visibleHeight) {
|
||||
val textPage = textPages.last()
|
||||
val textPage = pendingTextPage
|
||||
if (textPage.height < durY) {
|
||||
textPage.height = durY
|
||||
}
|
||||
textPage.text = stringBuilder.toString().ifEmpty { "本页无文字内容" }
|
||||
stringBuilder.clear()
|
||||
textPages.add(textPage)
|
||||
coroutineContext.ensureActive()
|
||||
onPageCompleted()
|
||||
textPages.add(TextPage())
|
||||
pendingTextPage = TextPage()
|
||||
durY = 0f
|
||||
}
|
||||
var height = size.height
|
||||
@ -334,7 +335,7 @@ class TextChapterLayout(
|
||||
height = visibleHeight
|
||||
}
|
||||
if (durY + height > visibleHeight) {
|
||||
val textPage = textPages.last()
|
||||
val textPage = pendingTextPage
|
||||
if (doublePage && absStartX < viewWidth / 2) {
|
||||
//当前页面左列结束
|
||||
textPage.leftLineSize = textPage.lineSize
|
||||
@ -346,9 +347,10 @@ class TextChapterLayout(
|
||||
}
|
||||
textPage.text = stringBuilder.toString().ifEmpty { "本页无文字内容" }
|
||||
stringBuilder.clear()
|
||||
textPages.add(textPage)
|
||||
coroutineContext.ensureActive()
|
||||
onPageCompleted()
|
||||
textPages.add(TextPage())
|
||||
pendingTextPage = TextPage()
|
||||
}
|
||||
// 双页的 durY 不正确,可能会小于实际高度
|
||||
if (textPage.height < durY) {
|
||||
@ -373,7 +375,7 @@ class TextChapterLayout(
|
||||
)
|
||||
calcTextLinePosition(textPages, textLine, stringBuilder.length)
|
||||
stringBuilder.append(" ") // 确保翻页时索引计算正确
|
||||
textPages.last().addLine(textLine)
|
||||
pendingTextPage.addLine(textLine)
|
||||
}
|
||||
return absStartX to durY + textHeight * paragraphSpacing / 10f
|
||||
}
|
||||
@ -403,8 +405,8 @@ class TextChapterLayout(
|
||||
}
|
||||
var durY = when {
|
||||
//标题y轴居中
|
||||
emptyContent && textPages.size == 1 -> {
|
||||
val textPage = textPages.last()
|
||||
emptyContent && textPages.isEmpty() -> {
|
||||
val textPage = pendingTextPage
|
||||
if (textPage.lineSize == 0) {
|
||||
val ty = (visibleHeight - layout.lineCount * textHeight) / 2
|
||||
if (ty > titleTopSpacing) ty else titleTopSpacing.toFloat()
|
||||
@ -423,7 +425,7 @@ class TextChapterLayout(
|
||||
}
|
||||
}
|
||||
|
||||
isTitle && textPages.size == 1 && textPages.last().lines.isEmpty() ->
|
||||
isTitle && textPages.isEmpty() && pendingTextPage.lines.isEmpty() ->
|
||||
y + titleTopSpacing
|
||||
|
||||
else -> y
|
||||
@ -431,7 +433,7 @@ class TextChapterLayout(
|
||||
for (lineIndex in 0 until layout.lineCount) {
|
||||
val textLine = TextLine(isTitle = isTitle)
|
||||
if (durY + textHeight > visibleHeight) {
|
||||
val textPage = textPages.last()
|
||||
val textPage = pendingTextPage
|
||||
if (doublePage && absStartX < viewWidth / 2) {
|
||||
//当前页面左列结束
|
||||
textPage.leftLineSize = textPage.lineSize
|
||||
@ -442,10 +444,11 @@ class TextChapterLayout(
|
||||
textPage.leftLineSize = textPage.lineSize
|
||||
}
|
||||
textPage.text = stringBuilder.toString()
|
||||
textPages.add(textPage)
|
||||
coroutineContext.ensureActive()
|
||||
onPageCompleted()
|
||||
//新建页面
|
||||
textPages.add(TextPage())
|
||||
pendingTextPage = TextPage()
|
||||
stringBuilder.clear()
|
||||
absStartX = paddingLeft
|
||||
}
|
||||
@ -514,7 +517,7 @@ class TextChapterLayout(
|
||||
calcTextLinePosition(textPages, textLine, stringBuilder.length)
|
||||
stringBuilder.append(lineText)
|
||||
textLine.upTopBottom(durY, textHeight, fontMetrics)
|
||||
val textPage = textPages.last()
|
||||
val textPage = pendingTextPage
|
||||
textPage.addLine(textLine)
|
||||
durY += textHeight * lineSpacingExtra
|
||||
if (textPage.height < durY) {
|
||||
@ -530,8 +533,8 @@ class TextChapterLayout(
|
||||
textLine: TextLine,
|
||||
sbLength: Int
|
||||
) {
|
||||
val lastLine = textPages.last().lines.lastOrNull { it.paragraphNum > 0 }
|
||||
?: textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull { it.paragraphNum > 0 }
|
||||
val lastLine = pendingTextPage.lines.lastOrNull { it.paragraphNum > 0 }
|
||||
?: textPages.lastOrNull()?.lines?.lastOrNull { it.paragraphNum > 0 }
|
||||
val paragraphNum = when {
|
||||
lastLine == null -> 1
|
||||
lastLine.isParagraphEnd -> lastLine.paragraphNum + 1
|
||||
@ -539,7 +542,7 @@ class TextChapterLayout(
|
||||
}
|
||||
textLine.paragraphNum = paragraphNum
|
||||
textLine.chapterPosition =
|
||||
(textPages.getOrNull(textPages.lastIndex - 1)?.lines?.lastOrNull()?.run {
|
||||
(textPages.lastOrNull()?.lines?.lastOrNull()?.run {
|
||||
chapterPosition + charSize + if (isParagraphEnd) 1 else 0
|
||||
} ?: 0) + sbLength
|
||||
textLine.pagePosition = sbLength
|
||||
|
Loading…
Reference in New Issue
Block a user