diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt index 712a6e3dc..17e183146 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt @@ -317,16 +317,16 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at /** * 选择开始文字 */ - fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { - selectStart.relativePos = relativePage + fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { + selectStart.relativePagePos = relativePagePos selectStart.lineIndex = lineIndex selectStart.charIndex = charIndex - val textLine = relativePage(relativePage).getLine(lineIndex) + val textLine = relativePage(relativePagePos).getLine(lineIndex) val textChar = textLine.getTextChar(charIndex) upSelectedStart( textChar.start, - textLine.lineBottom + relativeOffset(relativePage), - textLine.lineTop + relativeOffset(relativePage) + textLine.lineBottom + relativeOffset(relativePagePos), + textLine.lineTop + relativeOffset(relativePagePos) ) upSelectChars() } @@ -335,7 +335,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at * 选择结束文字 */ fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { - selectEnd.relativePos = relativePage + selectEnd.relativePagePos = relativePage selectEnd.lineIndex = lineIndex selectEnd.charIndex = charIndex val textLine = relativePage(relativePage).getLine(lineIndex) @@ -348,7 +348,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at val last = if (callBack.isScroll) 2 else 0 val textPos = TextPos(0, 0, 0) for (relativePos in 0..last) { - textPos.relativePos = relativePos + textPos.relativePagePos = relativePos for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) { textPos.lineIndex = lineIndex for ((charIndex, textChar) in textLine.textChars.withIndex()) { @@ -386,9 +386,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at fun getSelectedText(): String { val textPos = TextPos(0, 0, 0) val builder = StringBuilder() - for (relativePos in selectStart.relativePos..selectEnd.relativePos) { + for (relativePos in selectStart.relativePagePos..selectEnd.relativePagePos) { val textPage = relativePage(relativePos) - textPos.relativePos = relativePos + textPos.relativePagePos = relativePos textPage.textLines.forEachIndexed { lineIndex, textLine -> textPos.lineIndex = lineIndex textLine.textChars.forEachIndexed { charIndex, textChar -> @@ -412,7 +412,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } fun createBookmark(): Bookmark? { - val page = relativePage(selectStart.relativePos) + val page = relativePage(selectStart.relativePagePos) page.getTextChapter()?.let { chapter -> ReadBook.book?.let { book -> return book.createBookMark().apply { 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 ee9937c9f..46ac21f6f 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 @@ -262,7 +262,7 @@ class PageView(context: Context) : FrameLayout(context) { fun selectText( x: Float, y: Float, - select: (relativePage: Int, lineIndex: Int, charIndex: Int) -> Unit, + select: (relativePagePos: Int, lineIndex: Int, charIndex: Int) -> Unit, ) { return binding.contentTextView.selectText(x, y - headerHeight, select) } @@ -271,16 +271,16 @@ class PageView(context: Context) : FrameLayout(context) { binding.contentTextView.selectStartMove(x, y - headerHeight) } - fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { - binding.contentTextView.selectStartMoveIndex(relativePage, lineIndex, charIndex) + fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { + binding.contentTextView.selectStartMoveIndex(relativePagePos, lineIndex, charIndex) } fun selectEndMove(x: Float, y: Float) { binding.contentTextView.selectEndMove(x, y - headerHeight) } - fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { - binding.contentTextView.selectEndMoveIndex(relativePage, lineIndex, charIndex) + fun selectEndMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { + binding.contentTextView.selectEndMoveIndex(relativePagePos, lineIndex, charIndex) } fun cancelSelect() { @@ -291,8 +291,8 @@ class PageView(context: Context) : FrameLayout(context) { return binding.contentTextView.createBookmark() } - fun relativePage(relativePos: Int): TextPage { - return binding.contentTextView.relativePage(relativePos) + fun relativePage(relativePagePos: Int): TextPage { + return binding.contentTextView.relativePage(relativePagePos) } val selectedText: String get() = binding.contentTextView.getSelectedText() 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 a93d4da00..4aa71f670 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 @@ -22,6 +22,7 @@ import io.legado.app.ui.book.read.page.api.DataSource import io.legado.app.ui.book.read.page.delegate.* 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.TextPos import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.TextPageFactory import io.legado.app.utils.activity @@ -76,9 +77,7 @@ class ReadView(context: Context, attrs: AttributeSet) : } var isTextSelected = false private var pressOnTextSelected = false - private var firstRelativePage = 0 - private var firstLineIndex: Int = 0 - private var firstCharIndex: Int = 0 + private val initialTextPos = TextPos(0, 0, 0) val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop } private val tlRect = RectF() @@ -275,106 +274,73 @@ class ReadView(context: Context, attrs: AttributeSet) : */ private fun onLongPress() { kotlin.runCatching { - curPage.selectText(startX, startY) { relativePage, lineIndex, charIndex -> + curPage.selectText(startX, startY) { relativePos, lineIndex, charIndex -> isTextSelected = true - firstRelativePage = relativePage - firstLineIndex = lineIndex - firstCharIndex = charIndex - val page = curPage.relativePage(relativePage) - with(page) { - var lineStart = lineIndex - var lineEnd = lineIndex - var start: Int - var end: Int - if (lineIndex - 1 > 0 && lineIndex + 1 < lineSize) { - // 中间行 - val lineText = with(textLines) { - get(lineIndex - 1).text + get(lineIndex).text + get(lineIndex + 1).text - } - boundary.setText(lineText) - start = boundary.first() - end = boundary.next() - val cIndex = textLines[lineIndex - 1].text.length + charIndex - while (end != BreakIterator.DONE) { - if (cIndex in start until end) { - break - } - start = end - end = boundary.next() - } - if (start < textLines[lineIndex - 1].text.length) { - lineStart = lineIndex - 1 - } else { - start -= textLines[lineIndex - 1].text.length - } - if (end > textLines[lineIndex - 1].text.length + textLines[lineIndex].text.length) { - lineEnd = lineIndex + 1 - end = (end - textLines[lineIndex - 1].text.length - - textLines[lineIndex].text.length) - } else { - end = end - textLines[lineIndex - 1].text.length - 1 - } - } else if (lineIndex - 1 > 0) { - // 尾行 - val lineText = with(textLines) { - get(lineIndex - 1).text + get(lineIndex).text - } - boundary.setText(lineText) - start = boundary.first() - end = boundary.next() - val cIndex = textLines[lineIndex - 1].text.length + charIndex - while (end != BreakIterator.DONE) { - if (cIndex in start until end) { - break - } - start = end - end = boundary.next() - } - if (start < textLines[lineIndex - 1].text.length) { - lineStart = lineIndex - 1 - } else { - start -= textLines[lineIndex - 1].text.length - } - end = end - textLines[lineIndex - 1].text.length - 1 - } else if (lineIndex + 1 < lineSize) { - // 首行 - val lineText = with(textLines) { - get(lineIndex).text + get(lineIndex + 1).text - } - boundary.setText(lineText) - start = boundary.first() - end = boundary.next() - while (end != BreakIterator.DONE) { - if (charIndex in start until end) { - break - } - start = end - end = boundary.next() - } - if (end > textLines[lineIndex].text.length) { - lineEnd = lineIndex + 1 - end -= textLines[lineIndex].text.length - } else { - end -= 1 - } + initialTextPos.upData(relativePos, lineIndex, charIndex) + val startPos = TextPos(relativePos, lineIndex, charIndex) + val endPos = TextPos(relativePos, lineIndex, charIndex) + val page = curPage.relativePage(relativePos) + val stringBuilder = StringBuilder() + var cIndex = charIndex + var lineStart = lineIndex + var lineEnd = lineIndex + for (index in lineIndex - 1 downTo 0) { + val textLine = page.getLine(index) + if (textLine.isLastLine) { + break } else { - // 单行 - val lineText = textLines[lineIndex].text - boundary.setText(lineText) - start = boundary.first() - end = boundary.next() - while (end != BreakIterator.DONE) { - if (charIndex in start until end) { - break + stringBuilder.insert(0, textLine.text) + lineStart -= 1 + cIndex += textLine.charSize + } + } + for (index in lineIndex until page.lineSize) { + val textLine = page.getLine(index) + stringBuilder.append(textLine.text) + lineEnd += 1 + if (textLine.isLastLine) { + break + } + } + var start: Int + var end: Int + boundary.setText(stringBuilder.toString()) + start = boundary.first() + end = boundary.next() + while (end != BreakIterator.DONE) { + if (cIndex in start until end) { + break + } + start = end + end = boundary.next() + } + kotlin.run { + var ci = 0 + for (index in lineStart..lineEnd) { + val textLine = page.getLine(index) + for (j in 0 until textLine.charSize) { + if (ci == start) { + startPos.lineIndex = index + startPos.charIndex = j + } else if (ci == end) { + endPos.lineIndex = index + endPos.charIndex = j - 1 + return@run } - start = end - end = boundary.next() + ci++ } - end -= 1 } - curPage.selectStartMoveIndex(firstRelativePage, lineStart, start) - curPage.selectEndMoveIndex(firstRelativePage, lineEnd, end) } + curPage.selectStartMoveIndex( + startPos.relativePagePos, + startPos.lineIndex, + startPos.charIndex + ) + curPage.selectEndMoveIndex( + endPos.relativePagePos, + endPos.lineIndex, + endPos.charIndex + ) } } } @@ -431,31 +397,24 @@ class ReadView(context: Context, attrs: AttributeSet) : * 选择文本 */ private fun selectText(x: Float, y: Float) { - curPage.selectText(x, y) { relativePage, lineIndex, charIndex -> + curPage.selectText(x, y) { relativePagePos, lineIndex, charIndex -> + val compare = initialTextPos.compare(relativePagePos, lineIndex, charIndex) when { - relativePage > firstRelativePage -> { - curPage.selectStartMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectEndMoveIndex(relativePage, lineIndex, charIndex) - } - relativePage < firstRelativePage -> { - curPage.selectEndMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectStartMoveIndex(relativePage, lineIndex, charIndex) - } - lineIndex > firstLineIndex -> { - curPage.selectStartMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectEndMoveIndex(relativePage, lineIndex, charIndex) - } - lineIndex < firstLineIndex -> { - curPage.selectEndMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectStartMoveIndex(relativePage, lineIndex, charIndex) - } - charIndex > firstCharIndex -> { - curPage.selectStartMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectEndMoveIndex(relativePage, lineIndex, charIndex) + compare >= 0 -> { + curPage.selectStartMoveIndex(relativePagePos, lineIndex, charIndex) + curPage.selectEndMoveIndex( + initialTextPos.relativePagePos, + initialTextPos.lineIndex, + initialTextPos.charIndex + ) } else -> { - curPage.selectEndMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) - curPage.selectStartMoveIndex(relativePage, lineIndex, charIndex) + curPage.selectStartMoveIndex( + initialTextPos.relativePagePos, + initialTextPos.lineIndex, + initialTextPos.charIndex + ) + curPage.selectEndMoveIndex(relativePagePos, lineIndex, charIndex) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPos.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPos.kt index ce22bf92c..cc650c622 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPos.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPos.kt @@ -1,21 +1,27 @@ package io.legado.app.ui.book.read.page.entities data class TextPos( - var relativePos: Int, + var relativePagePos: Int, var lineIndex: Int, var charIndex: Int ) { + fun upData(relativePos: Int, lineIndex: Int, charIndex: Int) { + this.relativePagePos = relativePos + this.lineIndex = lineIndex + this.charIndex = charIndex + } + fun upData(pos: TextPos) { - relativePos = pos.relativePos + relativePagePos = pos.relativePagePos lineIndex = pos.lineIndex charIndex = pos.charIndex } fun compare(pos: TextPos): Int { return when { - relativePos < pos.relativePos -> -3 - relativePos > pos.relativePos -> 3 + relativePagePos < pos.relativePagePos -> -3 + relativePagePos > pos.relativePagePos -> 3 lineIndex < pos.lineIndex -> -2 lineIndex > pos.lineIndex -> 2 charIndex < pos.charIndex -> -1 @@ -23,4 +29,16 @@ data class TextPos( else -> 0 } } + + fun compare(relativePos: Int, lineIndex: Int, charIndex: Int): Int { + return when { + this.relativePagePos < relativePos -> -3 + this.relativePagePos > relativePos -> 3 + this.lineIndex < lineIndex -> -2 + this.lineIndex > lineIndex -> 2 + this.charIndex < charIndex -> -1 + this.charIndex > charIndex -> 1 + else -> 0 + } + } } \ No newline at end of file