pull/2268/head
kunfei 2 years ago
parent 3a80ae5eef
commit f9d3161d1a
  1. 6
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  2. 36
      app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
  3. 21
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt
  4. 18
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
  5. 23
      app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt

@ -384,7 +384,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
// calculate search result's lineIndex
val currentPage = pages[pageIndex]
val curTextLines = currentPage.textLines
val curTextLines = currentPage.lines
var lineIndex = 0
var curLine = curTextLines[lineIndex]
length = length - currentPage.text.length + curLine.text.length
@ -397,7 +397,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
}
// charIndex
val currentLine = currentPage.textLines[lineIndex]
val currentLine = currentPage.lines[lineIndex]
var curLineLength = currentLine.text.length
if (currentLine.isParagraphEnd) curLineLength++
length -= curLineLength
@ -411,7 +411,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
charIndex2 = charIndex + queryLength - curLineLength - 1
}
// changePage
if ((lineIndex + addLine + 1) > currentPage.textLines.size) {
if ((lineIndex + addLine + 1) > currentPage.lines.size) {
addLine = -1
charIndex2 = charIndex + queryLength - curLineLength - 1
}

@ -16,7 +16,10 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.lib.theme.accentColor
import io.legado.app.model.ReadBook
import io.legado.app.ui.book.read.page.entities.*
import io.legado.app.ui.book.read.page.entities.TextColumn
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.TextPos
import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.ui.book.read.page.provider.ImageProvider
import io.legado.app.ui.book.read.page.provider.TextPageFactory
@ -105,7 +108,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
*/
private fun drawPage(canvas: Canvas) {
var relativeOffset = relativeOffset(0)
textPage.textLines.forEach { textLine ->
textPage.lines.forEach { textLine ->
draw(canvas, textPage, textLine, relativeOffset)
}
if (!callBack.isScroll) return
@ -113,14 +116,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
if (!pageFactory.hasNext()) return
val textPage1 = relativePage(1)
relativeOffset = relativeOffset(1)
textPage1.textLines.forEach { textLine ->
textPage1.lines.forEach { textLine ->
draw(canvas, textPage1, textLine, relativeOffset)
}
if (!pageFactory.hasNextPlus()) return
relativeOffset = relativeOffset(2)
if (relativeOffset < ChapterProvider.visibleHeight) {
val textPage2 = relativePage(2)
textPage2.textLines.forEach { textLine ->
textPage2.lines.forEach { textLine ->
draw(canvas, textPage2, textLine, relativeOffset)
}
}
@ -164,7 +167,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
val reviewCountPaint = TextPaint()
reviewCountPaint.textSize = textPaint.textSize * 0.6F
reviewCountPaint.color = textColor
textLine.textColumns.forEach {
textLine.columns.forEach {
when (it.style) {
0 -> {
textPaint.color = textColor
@ -460,9 +463,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
if (relativeOffset >= ChapterProvider.visibleHeight) return
}
val textPage = relativePage(relativePos)
for ((lineIndex, textLine) in textPage.textLines.withIndex()) {
for ((lineIndex, textLine) in textPage.lines.withIndex()) {
if (textLine.isTouch(x, y, relativeOffset)) {
for ((charIndex, textColumn) in textLine.textColumns.withIndex()) {
for ((charIndex, textColumn) in textLine.columns.withIndex()) {
if (textColumn.isTouch(x)) {
touched.invoke(
relativeOffset,
@ -486,7 +489,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectStart.lineIndex = lineIndex
selectStart.charIndex = charIndex
val textLine = relativePage(relativePagePos).getLine(lineIndex)
val textColumn = textLine.getTextColumn(charIndex)
val textColumn = textLine.getColumn(charIndex)
upSelectedStart(
textColumn.start,
textLine.lineBottom + relativeOffset(relativePagePos),
@ -503,7 +506,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
selectEnd.lineIndex = lineIndex
selectEnd.charIndex = charIndex
val textLine = relativePage(relativePage).getLine(lineIndex)
val textColumn = textLine.getTextColumn(charIndex)
val textColumn = textLine.getColumn(charIndex)
upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset(relativePage))
upSelectChars()
}
@ -513,14 +516,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
val textPos = TextPos(0, 0, 0)
for (relativePos in 0..last) {
textPos.relativePagePos = relativePos
for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) {
for ((lineIndex, textLine) in relativePage(relativePos).lines.withIndex()) {
textPos.lineIndex = lineIndex
for ((charIndex, textColumn) in textLine.textColumns.withIndex()) {
for ((charIndex, textColumn) in textLine.columns.withIndex()) {
textPos.charIndex = charIndex
if (textColumn.style == 2) continue
textColumn.selected =
textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0
textColumn.isSearchResult = textColumn.selected && callBack.isSelectingSearchResult
textColumn.isSearchResult =
textColumn.selected && callBack.isSelectingSearchResult
}
}
}
@ -538,8 +542,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
fun cancelSelect(fromSearchExit: Boolean = false) {
val last = if (callBack.isScroll) 2 else 0
for (relativePos in 0..last) {
relativePage(relativePos).textLines.forEach { textLine ->
textLine.textColumns.forEach {
relativePage(relativePos).lines.forEach { textLine ->
textLine.columns.forEach {
it.selected = false
if (fromSearchExit) it.isSearchResult = false
}
@ -555,9 +559,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
for (relativePos in selectStart.relativePagePos..selectEnd.relativePagePos) {
val textPage = relativePage(relativePos)
textPos.relativePagePos = relativePos
textPage.textLines.forEachIndexed { lineIndex, textLine ->
textPage.lines.forEachIndexed { lineIndex, textLine ->
textPos.lineIndex = lineIndex
textLine.textColumns.forEachIndexed { charIndex, textColumn ->
textLine.columns.forEachIndexed { charIndex, textColumn ->
textPos.charIndex = charIndex
val compareStart = textPos.compare(selectStart)
val compareEnd = textPos.compare(selectEnd)

@ -10,7 +10,7 @@ import io.legado.app.utils.textHeight
@Suppress("unused", "MemberVisibilityCanBePrivate")
data class TextLine(
var text: String = "",
val textColumns: ArrayList<TextColumn> = arrayListOf(),
private val textColumns: ArrayList<TextColumn> = arrayListOf(),
val reviewCount: Int = 0,
var lineTop: Float = 0f,
var lineBase: Float = 0f,
@ -21,30 +21,35 @@ data class TextLine(
var isImage: Boolean = false
) {
val columns: List<TextColumn> get() = textColumns
val charSize: Int get() = textColumns.size
val lineStart: Float get() = textColumns.firstOrNull()?.start ?: 0f
val lineEnd: Float get() = textColumns.lastOrNull()?.end ?: 0f
fun upTopBottom(durY: Float, textPaint: TextPaint) {
lineTop = ChapterProvider.paddingTop + durY
lineBottom = lineTop + textPaint.textHeight
lineBase = lineBottom - textPaint.fontMetrics.descent
fun addColumn(column: TextColumn) {
textColumns.add(column)
}
fun getTextColumn(index: Int): TextColumn {
fun getColumn(index: Int): TextColumn {
return textColumns.getOrElse(index) {
textColumns.last()
}
}
fun getTextColumnReverseAt(index: Int): TextColumn {
fun getColumnReverseAt(index: Int): TextColumn {
return textColumns[textColumns.lastIndex - index]
}
fun getTextColumnsCount(): Int {
fun getColumnsCount(): Int {
return textColumns.size
}
fun upTopBottom(durY: Float, textPaint: TextPaint) {
lineTop = ChapterProvider.paddingTop + durY
lineBottom = lineTop + textPaint.textHeight
lineBase = lineBottom - textPaint.fontMetrics.descent
}
fun isTouch(x: Float, y: Float, relativeOffset: Float): Boolean {
return y > lineTop + relativeOffset
&& y < lineBottom + relativeOffset

@ -19,7 +19,7 @@ data class TextPage(
var index: Int = 0,
var text: String = appCtx.getString(R.string.data_loading),
var title: String = "",
val textLines: ArrayList<TextLine> = arrayListOf(),
private val textLines: ArrayList<TextLine> = arrayListOf(),
var pageSize: Int = 0,
var chapterSize: Int = 0,
var chapterIndex: Int = 0,
@ -27,10 +27,15 @@ data class TextPage(
var leftLineSize: Int = 0
) {
val lineSize get() = textLines.size
val charSize get() = text.length
val lines: List<TextLine> get() = textLines
val lineSize: Int get() = textLines.size
val charSize: Int get() = text.length
var isMsgPage: Boolean = false
fun addLine(line: TextLine) {
textLines.add(line)
}
fun getLine(index: Int): TextLine {
return textLines.getOrElse(index) {
textLines.last()
@ -84,7 +89,7 @@ data class TextPage(
}
/**
* 计算文字位置
* 计算文字位置,只用作单页面内容
*/
@Suppress("DEPRECATION")
fun format(): TextPage {
@ -113,12 +118,11 @@ data class TextPage(
val char = textLine.text[i].toString()
val cw = StaticLayout.getDesiredWidth(char, ChapterProvider.contentPaint)
val x1 = x + cw
textLine.textColumns.add(
textLine.addColumn(
TextColumn(
char,
start = x,
end = x1,
style = if (textLine.text.length - 1 == index && char == "\uD83D\uDCAC") 2 else 0
end = x1
)
)
x = x1

@ -26,7 +26,10 @@ import java.util.*
*/
@Suppress("DEPRECATION")
object ChapterProvider {
//用于图片字的替换
private const val srcReplaceChar = ""
//用于评论按钮的替换
private const val reviewChar = "\uD83D\uDCAC"
@JvmStatic
@ -264,10 +267,10 @@ object ChapterProvider {
} else {
Pair(0f, width.toFloat())
}
textLine.textColumns.add(
textLine.addColumn(
TextColumn(charData = src, start = x + start, end = x + end, style = 1)
)
textPages.last().textLines.add(textLine)
textPages.last().addLine(textLine)
}
return durY + paragraphSpacing / 10f
}
@ -306,7 +309,7 @@ object ChapterProvider {
if (fistLine.lineTop < textLayoutHeight + titleTopSpacing) {
textLayoutHeight = fistLine.lineTop - titleTopSpacing
}
textPage.textLines.forEach {
textPage.lines.forEach {
it.lineTop = it.lineTop - textLayoutHeight
it.lineBase = it.lineBase - textLayoutHeight
it.lineBottom = it.lineBottom - textLayoutHeight
@ -314,7 +317,7 @@ object ChapterProvider {
y - textLayoutHeight
}
}
isTitle && textPages.size == 1 && textPages.last().textLines.isEmpty() ->
isTitle && textPages.size == 1 && textPages.last().lines.isEmpty() ->
y + titleTopSpacing
else -> y
}
@ -382,7 +385,7 @@ object ChapterProvider {
if (textLine.isParagraphEnd) {
stringBuilder.append("\n")
}
textPages.last().textLines.add(textLine)
textPages.last().addLine(textLine)
textLine.upTopBottom(durY, textPaint)
durY += textPaint.textHeight * lineSpacingExtra
textPages.last().height = durY
@ -412,7 +415,7 @@ object ChapterProvider {
val icw = StaticLayout.getDesiredWidth(bodyIndent, textPaint) / bodyIndent.length
for (char in bodyIndent.toStringArray()) {
val x1 = x + icw
textLine.textColumns.add(
textLine.addColumn(
TextColumn(
charData = char,
start = absStartX + x,
@ -496,7 +499,7 @@ object ChapterProvider {
if (srcList != null && char == srcReplaceChar) {
val src = srcList.removeFirst()
ImageProvider.cacheImage(book, src, ReadBook.bookSource)
textLine.textColumns.add(
textLine.addColumn(
TextColumn(
charData = src,
start = absStartX + xStart,
@ -505,7 +508,7 @@ object ChapterProvider {
)
)
} else {
textLine.textColumns.add(
textLine.addColumn(
TextColumn(
charData = char,
start = absStartX + xStart,
@ -521,11 +524,11 @@ object ChapterProvider {
*/
private fun exceed(absStartX: Int, textLine: TextLine, words: Array<String>) {
val visibleEnd = absStartX + visibleWidth
val endX = textLine.textColumns.lastOrNull()?.end ?: return
val endX = textLine.columns.lastOrNull()?.end ?: return
if (endX > visibleEnd) {
val cc = (endX - visibleEnd) / words.size
for (i in 0..words.lastIndex) {
textLine.getTextColumnReverseAt(i).let {
textLine.getColumnReverseAt(i).let {
val py = cc * (words.size - i)
it.start = it.start - py
it.end = it.end - py

Loading…
Cancel
Save