[优化] 恢复标题分段功能

This commit is contained in:
HapeLee committed 2026-01-18 15:42:35 +08:00
1 parent d28d3ed226
commit a770b3c052
3 files changed
+87 -35

No files matched your search

@@ -1,4 +1,4 @@
package io.legado.app.ui.book.read.page.entities package io.legado.app.ui.book.read.page.entities.column
import android.graphics.Canvas import android.graphics.Canvas
import android.os.Build import android.os.Build
@@ -7,7 +7,7 @@ import androidx.annotation.Keep
import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ReadBookConfig
import io.legado.app.ui.book.read.page.ContentTextView import io.legado.app.ui.book.read.page.ContentTextView
import io.legado.app.ui.book.read.page.TextBaseColumn import io.legado.app.ui.book.read.page.TextBaseColumn
import io.legado.app.ui.book.read.page.entities.TextLine.Companion.emptyTextLine import io.legado.app.ui.book.read.page.entities.TextLine
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
/** /**
@@ -23,7 +23,7 @@ data class TextHtmlColumn(
val linkUrl: String? val linkUrl: String?
) : TextBaseColumn { ) : TextBaseColumn {
override var textLine: TextLine = emptyTextLine override var textLine: TextLine = TextLine.Companion.emptyTextLine
private val textPaint: TextPaint by lazy { private val textPaint: TextPaint by lazy {
TextPaint(ChapterProvider.contentPaint).apply { TextPaint(ChapterProvider.contentPaint).apply {
@@ -28,11 +28,11 @@ import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.ImageProvider import io.legado.app.model.ImageProvider
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
import io.legado.app.ui.book.read.page.entities.TextChapter import io.legado.app.ui.book.read.page.entities.TextChapter
import io.legado.app.ui.book.read.page.entities.TextHtmlColumn
import io.legado.app.ui.book.read.page.entities.TextLine import io.legado.app.ui.book.read.page.entities.TextLine
import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.ui.book.read.page.entities.column.ImageColumn import io.legado.app.ui.book.read.page.entities.column.ImageColumn
import io.legado.app.ui.book.read.page.entities.column.TextColumn import io.legado.app.ui.book.read.page.entities.column.TextColumn
import io.legado.app.ui.book.read.page.entities.column.TextHtmlColumn
import io.legado.app.ui.book.read.page.provider.ChapterProvider.reviewChar import io.legado.app.ui.book.read.page.provider.ChapterProvider.reviewChar
import io.legado.app.ui.book.read.page.provider.ChapterProvider.srcReplaceChar import io.legado.app.ui.book.read.page.provider.ChapterProvider.srcReplaceChar
import io.legado.app.ui.book.read.page.provider.ChapterProvider.srcReplaceCharC import io.legado.app.ui.book.read.page.provider.ChapterProvider.srcReplaceCharC
@@ -95,7 +95,10 @@ class TextChapterLayout(
private val textFullJustify = ReadBookConfig.textFullJustify private val textFullJustify = ReadBookConfig.textFullJustify
private val adaptSpecialStyle = AppConfig.adaptSpecialStyle private val adaptSpecialStyle = AppConfig.adaptSpecialStyle
private val pageAnim = book.getPageAnim() private val pageAnim = book.getPageAnim()
private val titleSegType = ReadBookConfig.titleSegType
private val titleSegDistance = ReadBookConfig.titleSegDistance
private val titleSegFlag = ReadBookConfig.titleSegFlag
private val titleSegScaling = ReadBookConfig.titleSegScaling
private var pendingTextPage = TextPage() private var pendingTextPage = TextPage()
private val bookChapter inline get() = textChapter.chapter private val bookChapter inline get() = textChapter.chapter
@@ -206,6 +209,44 @@ class TextChapterLayout(
} }
} }
private fun parseTitleSegments(
rawTitle: String,
segType: Int,
segDistance: Int,
segFlag: String
): List<String> {
if (rawTitle.isBlank()) return emptyList()
return when (segType) {
0 -> listOf(rawTitle)
1 -> {
if (segDistance <= 0 || segDistance >= rawTitle.length)
listOf(rawTitle)
else
listOf(
rawTitle.take(segDistance),
rawTitle.substring(segDistance)
)
}
2 -> {
val flags = segFlag.split(",").map { it.trim() }.filter { it.isNotEmpty() }
if (flags.isEmpty()) return listOf(rawTitle)
val pattern = flags.joinToString("|") { Regex.escape(it) }
val regex = Regex("(?<=$pattern)")
val segments = rawTitle.split(regex)
.map { it.trim() }
.filter { it.isNotEmpty() }
segments.ifEmpty { listOf(rawTitle) }
}
else -> listOf(rawTitle)
}
}
/** /**
* 获取拆分完的章节数据 * 获取拆分完的章节数据
*/ */
@@ -221,37 +262,48 @@ class TextChapterLayout(
val isTextImageStyle = imageStyle.equals(Book.imgStyleText, true) val isTextImageStyle = imageStyle.equals(Book.imgStyleText, true)
if (titleMode != 2 || bookChapter.isVolume || contents.isEmpty()) { if (titleMode != 2 || bookChapter.isVolume || contents.isEmpty()) {
//标题非隐藏 val baseTitles = displayTitle.splitNotBlank("\n")
displayTitle.splitNotBlank("\n").forEach { text -> baseTitles.forEach { rawTitle ->
val srcList = LinkedList<String>() val titleSegments = parseTitleSegments(
val reviewImg = bookChapter.reviewImg rawTitle,
var reviewTxt = "" titleSegType,
if (!reviewImg.isNullOrEmpty()) { titleSegDistance,
srcList.add(reviewImg) titleSegFlag
reviewTxt = if (reviewImg.contains("TEXT")) {
reviewChar
} else {
srcReplaceChar
}
}
setTypeText(
book,
text + reviewTxt,
titlePaint,
titlePaintTextHeight,
titlePaintFontMetrics,
imageStyle,
srcList = srcList.ifEmpty { null },
isTitle = true,
emptyContent = contents.isEmpty(),
isVolumeTitle = bookChapter.isVolume
) )
pendingTextPage.lines.last().isParagraphEnd = true titleSegments.forEachIndexed { index, segment ->
stringBuilder.append("\n") val srcList = LinkedList<String>()
val reviewImg = bookChapter.reviewImg
var reviewTxt = ""
if (reviewImg != null) {
srcList.add(reviewImg)
reviewTxt = if (reviewImg.contains("TEXT")) {
reviewChar
} else {
srcReplaceChar
}
}
val paint = if (index == 0) titlePaint else {
TextPaint(titlePaint).apply {
textSize = titlePaint.textSize * titleSegScaling
}
}
setTypeText(
book,
segment + reviewTxt,
paint,
titlePaintTextHeight,
titlePaintFontMetrics,
imageStyle,
srcList = srcList.ifEmpty { null },
isTitle = true,
emptyContent = contents.isEmpty(),
isVolumeTitle = bookChapter.isVolume
)
pendingTextPage.lines.last().isParagraphEnd = true
stringBuilder.append("\n")
}
} }
durY += titleBottomSpacing durY += titleBottomSpacing
// 如果是单图模式且当前页有内容,强制分页
if (isSingleImageStyle && pendingTextPage.lines.isNotEmpty() && contents.isNotEmpty()) { if (isSingleImageStyle && pendingTextPage.lines.isNotEmpty() && contents.isNotEmpty()) {
prepareNextPageIfNeed() prepareNextPageIfNeed()
} }
+2 -2
View File
@@ -1,5 +1,5 @@
VERSION_MAJOR=3 VERSION_MAJOR=3
VERSION_MINOR=26 VERSION_MINOR=26
VERSION_PATCH=7 VERSION_PATCH=8
VERSION_SUFFIX=0 VERSION_SUFFIX=1
# 1 = Pre, 0 = Release # 1 = Pre, 0 = Release