kunfei 4 лет назад
Родитель
Сommit
1181d93452

+ 10 - 10
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 {

+ 7 - 7
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()

+ 78 - 119
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)
                 }
             }
         }

+ 22 - 4
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
+        }
+    }
 }