diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index 01c222b75..796cb9b1a 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -19,7 +19,9 @@ import io.legado.app.model.localBook.TextFile import io.legado.app.model.webBook.WebBook import io.legado.app.service.BaseReadAloudService 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 import io.legado.app.utils.stackTraceStr import io.legado.app.utils.toastOnUi import kotlinx.coroutines.CoroutineScope @@ -230,7 +232,7 @@ object ReadBook : CoroutineScope by MainScope() { callBack?.upMenuView() AppLog.putDebug("moveToNextChapter-curPageChanged()") curPageChanged() - curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it) } + curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it, upContent) } return true } else { AppLog.putDebug("跳转下一章失败,没有下一章") @@ -260,7 +262,7 @@ object ReadBook : CoroutineScope by MainScope() { saveRead() callBack?.upMenuView() curPageChanged() - curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it) } + curTextChapter?.let { callBack?.onCurrentTextChapterChanged(it, upContent) } return true } else { return false @@ -292,14 +294,27 @@ object ReadBook : CoroutineScope by MainScope() { curPageChanged(true) } + fun openChapter(index: Int, durChapterPos: Int = 0, success: (() -> Unit)? = null) { + if (index < chapterSize) { + clearTextChapter() + callBack?.upContent() + durChapterIndex = index + ReadBook.durChapterPos = durChapterPos + saveRead() + loadContent(resetPageOffset = true) { + success?.invoke() + } + } + } + /** * 当前页面变化 */ - private fun curPageChanged(pauseReadAloud: Boolean = false) { + private fun curPageChanged(pageChanged: Boolean = false) { callBack?.pageChanged() if (BaseReadAloudService.isRun) { val scrollPageAnim = pageAnim() == 3 - if (scrollPageAnim && pauseReadAloud) { + if (scrollPageAnim && pageChanged) { ReadAloud.pause(appCtx) } else { readAloud(!BaseReadAloudService.pause) @@ -484,38 +499,49 @@ object ReadBook : CoroutineScope by MainScope() { ) val contents = contentProcessor .getContent(book, chapter, content, includeTitle = false) - val textChapter = ChapterProvider.getTextChapterAsync( - book, - chapter, - displayTitle, - contents, - chapterSize, - this@ReadBook - ) + val textChapter = + ChapterProvider.getTextChapterAsync(chapter, displayTitle, contents, chapterSize) when (val offset = chapter.index - durChapterIndex) { 0 -> { curTextChapter?.cancelLayout() curTextChapter = textChapter - if (upContent) callBack?.upContent(offset, resetPageOffset) + if (resetPageOffset) { + callBack?.resetPageOffset() + } callBack?.upMenuView() curPageChanged() callBack?.contentLoadFinish() - callBack?.onCurrentTextChapterChanged(textChapter) + callBack?.onCurrentTextChapterChanged(textChapter, upContent) } -1 -> { prevTextChapter?.cancelLayout() prevTextChapter = textChapter - if (upContent) callBack?.upContent(offset, resetPageOffset) + if (upContent) { + textChapter.setProgressListener(object : LayoutProgressListener { + override fun onLayoutCompleted() { + callBack?.upContent(offset, resetPageOffset) + } + }) + } } 1 -> { nextTextChapter?.cancelLayout() nextTextChapter = textChapter - if (upContent) callBack?.upContent(offset, resetPageOffset) + if (upContent) { + textChapter.setProgressListener(object : LayoutProgressListener { + override fun onLayoutPageCompleted(index: Int, page: TextPage) { + if (index > 1) { + return + } + callBack?.upContent(offset, resetPageOffset) + } + }) + } } } - Unit + textChapter.createLayout(this@ReadBook, book, contents) }.onError { AppLog.put("ChapterProvider ERROR", it) appCtx.toastOnUi("ChapterProvider ERROR:\n${it.stackTraceStr}") @@ -650,7 +676,9 @@ object ReadBook : CoroutineScope by MainScope() { fun notifyBookChanged() - fun onCurrentTextChapterChanged(textChapter: TextChapter) + fun onCurrentTextChapterChanged(textChapter: TextChapter, upContent: Boolean = true) + + fun resetPageOffset() } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index a0bcf2649..e84901a42 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -126,6 +126,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import kotlin.math.max /** * 阅读界面 @@ -233,6 +234,7 @@ class ReadBookActivity : BaseReadBookActivity(), binding.readMenu.upSeekBar() } } + private var upContent = true //恢复跳转前进度对话框的交互结果 private var confirmRestoreProcess: Boolean? = null @@ -936,7 +938,9 @@ class ReadBookActivity : BaseReadBookActivity(), ) { lifecycleScope.launch { binding.readView.upContent(relativePosition, resetPageOffset) - upSeekBarProgress() + if (relativePosition == 0) { + upSeekBarProgress() + } loadStates = false success?.invoke() } @@ -1369,16 +1373,38 @@ class ReadBookActivity : BaseReadBookActivity(), binding.readView.autoPager.resume() } - override fun onCurrentTextChapterChanged(textChapter: TextChapter) { + 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() } @@ -1388,6 +1414,10 @@ class ReadBookActivity : BaseReadBookActivity(), binding.readView.onLayoutException(e) } + override fun resetPageOffset() { + binding.readView.resetPageOffset() + } + /* 全文搜索跳转 */ private fun skipToSearch(searchResult: SearchResult) { val previousResult = binding.searchMenu.previousSearchResult diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index 255e99151..8e73e5e84 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -317,16 +317,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } fun openChapter(index: Int, durChapterPos: Int = 0, success: (() -> Unit)? = null) { - if (index < ReadBook.chapterSize) { - ReadBook.clearTextChapter() - ReadBook.callBack?.upContent() - ReadBook.durChapterIndex = index - ReadBook.durChapterPos = durChapterPos - ReadBook.saveRead() - ReadBook.loadContent(resetPageOffset = true) { - success?.invoke() - } - } + ReadBook.openChapter(index, durChapterPos, success) } fun removeFromBookshelf(success: (() -> Unit)?) { diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt index c08339218..a668377d6 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt @@ -288,6 +288,10 @@ class PageView(context: Context) : FrameLayout(context) { binding.contentTextView.setContent(textPage) } + fun invalidateContentView() { + binding.contentTextView.invalidate() + } + /** * 设置无障碍文本 */ diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt index c365adb40..bd7e12b7e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt @@ -527,7 +527,11 @@ class ReadView(context: Context, attrs: AttributeSet) : curPage.setContentDescription(pageFactory.curPage.text) } if (isScroll && !isAutoPage) { - curPage.setContent(pageFactory.curPage, resetPageOffset) + if (relativePosition == 0) { + curPage.setContent(pageFactory.curPage, resetPageOffset) + } else { + curPage.invalidateContentView() + } } else { when (relativePosition) { -1 -> prevPage.setContent(pageFactory.prevPage) @@ -662,34 +666,11 @@ class ReadView(context: Context, attrs: AttributeSet) : } override fun onLayoutPageCompleted(index: Int, page: TextPage) { - val line = page.lines.first() - val durChapterPos = ReadBook.durChapterPos - val startPos = line.chapterPosition - val endPos = startPos + line.charSize - if (durChapterPos in startPos.. y } for (lineIndex in 0 until layout.lineCount) { - coroutineContext.ensureActive() val textLine = TextLine(isTitle = isTitle) if (durY + textHeight > visibleHeight) { val textPage = textPages.last() @@ -438,6 +442,7 @@ class TextChapterLayout( textPage.leftLineSize = textPage.lineSize } textPage.text = stringBuilder.toString() + coroutineContext.ensureActive() onPageCompleted() //新建页面 textPages.add(TextPage())