mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
优化
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user