pull/1794/head
kunfei 2 years ago
parent 4fdd216aa9
commit d01c0e98ab
  1. 20
      app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
  2. 14
      app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
  3. 197
      app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt
  4. 26
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPos.kt

@ -317,16 +317,16 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
/** /**
* 选择开始文字 * 选择开始文字
*/ */
fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) {
selectStart.relativePos = relativePage selectStart.relativePagePos = relativePagePos
selectStart.lineIndex = lineIndex selectStart.lineIndex = lineIndex
selectStart.charIndex = charIndex selectStart.charIndex = charIndex
val textLine = relativePage(relativePage).getLine(lineIndex) val textLine = relativePage(relativePagePos).getLine(lineIndex)
val textChar = textLine.getTextChar(charIndex) val textChar = textLine.getTextChar(charIndex)
upSelectedStart( upSelectedStart(
textChar.start, textChar.start,
textLine.lineBottom + relativeOffset(relativePage), textLine.lineBottom + relativeOffset(relativePagePos),
textLine.lineTop + relativeOffset(relativePage) textLine.lineTop + relativeOffset(relativePagePos)
) )
upSelectChars() upSelectChars()
} }
@ -335,7 +335,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
* 选择结束文字 * 选择结束文字
*/ */
fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) {
selectEnd.relativePos = relativePage selectEnd.relativePagePos = relativePage
selectEnd.lineIndex = lineIndex selectEnd.lineIndex = lineIndex
selectEnd.charIndex = charIndex selectEnd.charIndex = charIndex
val textLine = relativePage(relativePage).getLine(lineIndex) 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 last = if (callBack.isScroll) 2 else 0
val textPos = TextPos(0, 0, 0) val textPos = TextPos(0, 0, 0)
for (relativePos in 0..last) { for (relativePos in 0..last) {
textPos.relativePos = relativePos textPos.relativePagePos = relativePos
for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) { for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) {
textPos.lineIndex = lineIndex textPos.lineIndex = lineIndex
for ((charIndex, textChar) in textLine.textChars.withIndex()) { for ((charIndex, textChar) in textLine.textChars.withIndex()) {
@ -386,9 +386,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
fun getSelectedText(): String { fun getSelectedText(): String {
val textPos = TextPos(0, 0, 0) val textPos = TextPos(0, 0, 0)
val builder = StringBuilder() val builder = StringBuilder()
for (relativePos in selectStart.relativePos..selectEnd.relativePos) { for (relativePos in selectStart.relativePagePos..selectEnd.relativePagePos) {
val textPage = relativePage(relativePos) val textPage = relativePage(relativePos)
textPos.relativePos = relativePos textPos.relativePagePos = relativePos
textPage.textLines.forEachIndexed { lineIndex, textLine -> textPage.textLines.forEachIndexed { lineIndex, textLine ->
textPos.lineIndex = lineIndex textPos.lineIndex = lineIndex
textLine.textChars.forEachIndexed { charIndex, textChar -> textLine.textChars.forEachIndexed { charIndex, textChar ->
@ -412,7 +412,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} }
fun createBookmark(): Bookmark? { fun createBookmark(): Bookmark? {
val page = relativePage(selectStart.relativePos) val page = relativePage(selectStart.relativePagePos)
page.getTextChapter()?.let { chapter -> page.getTextChapter()?.let { chapter ->
ReadBook.book?.let { book -> ReadBook.book?.let { book ->
return book.createBookMark().apply { return book.createBookMark().apply {

@ -262,7 +262,7 @@ class PageView(context: Context) : FrameLayout(context) {
fun selectText( fun selectText(
x: Float, y: Float, 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) return binding.contentTextView.selectText(x, y - headerHeight, select)
} }
@ -271,16 +271,16 @@ class PageView(context: Context) : FrameLayout(context) {
binding.contentTextView.selectStartMove(x, y - headerHeight) binding.contentTextView.selectStartMove(x, y - headerHeight)
} }
fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) {
binding.contentTextView.selectStartMoveIndex(relativePage, lineIndex, charIndex) binding.contentTextView.selectStartMoveIndex(relativePagePos, lineIndex, charIndex)
} }
fun selectEndMove(x: Float, y: Float) { fun selectEndMove(x: Float, y: Float) {
binding.contentTextView.selectEndMove(x, y - headerHeight) binding.contentTextView.selectEndMove(x, y - headerHeight)
} }
fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectEndMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) {
binding.contentTextView.selectEndMoveIndex(relativePage, lineIndex, charIndex) binding.contentTextView.selectEndMoveIndex(relativePagePos, lineIndex, charIndex)
} }
fun cancelSelect() { fun cancelSelect() {
@ -291,8 +291,8 @@ class PageView(context: Context) : FrameLayout(context) {
return binding.contentTextView.createBookmark() return binding.contentTextView.createBookmark()
} }
fun relativePage(relativePos: Int): TextPage { fun relativePage(relativePagePos: Int): TextPage {
return binding.contentTextView.relativePage(relativePos) return binding.contentTextView.relativePage(relativePagePos)
} }
val selectedText: String get() = binding.contentTextView.getSelectedText() val selectedText: String get() = binding.contentTextView.getSelectedText()

@ -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.delegate.*
import io.legado.app.ui.book.read.page.entities.PageDirection 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.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.ChapterProvider
import io.legado.app.ui.book.read.page.provider.TextPageFactory import io.legado.app.ui.book.read.page.provider.TextPageFactory
import io.legado.app.utils.activity import io.legado.app.utils.activity
@ -76,9 +77,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
} }
var isTextSelected = false var isTextSelected = false
private var pressOnTextSelected = false private var pressOnTextSelected = false
private var firstRelativePage = 0 private val initialTextPos = TextPos(0, 0, 0)
private var firstLineIndex: Int = 0
private var firstCharIndex: Int = 0
val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop } val slopSquare by lazy { ViewConfiguration.get(context).scaledTouchSlop }
private val tlRect = RectF() private val tlRect = RectF()
@ -275,106 +274,73 @@ class ReadView(context: Context, attrs: AttributeSet) :
*/ */
private fun onLongPress() { private fun onLongPress() {
kotlin.runCatching { kotlin.runCatching {
curPage.selectText(startX, startY) { relativePage, lineIndex, charIndex -> curPage.selectText(startX, startY) { relativePos, lineIndex, charIndex ->
isTextSelected = true isTextSelected = true
firstRelativePage = relativePage initialTextPos.upData(relativePos, lineIndex, charIndex)
firstLineIndex = lineIndex val startPos = TextPos(relativePos, lineIndex, charIndex)
firstCharIndex = charIndex val endPos = TextPos(relativePos, lineIndex, charIndex)
val page = curPage.relativePage(relativePage) val page = curPage.relativePage(relativePos)
with(page) { val stringBuilder = StringBuilder()
var lineStart = lineIndex var cIndex = charIndex
var lineEnd = lineIndex var lineStart = lineIndex
var start: Int var lineEnd = lineIndex
var end: Int for (index in lineIndex - 1 downTo 0) {
if (lineIndex - 1 > 0 && lineIndex + 1 < lineSize) { val textLine = page.getLine(index)
// 中间行 if (textLine.isLastLine) {
val lineText = with(textLines) { break
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
}
} else { } else {
// 单行 stringBuilder.insert(0, textLine.text)
val lineText = textLines[lineIndex].text lineStart -= 1
boundary.setText(lineText) cIndex += textLine.charSize
start = boundary.first() }
end = boundary.next() }
while (end != BreakIterator.DONE) { for (index in lineIndex until page.lineSize) {
if (charIndex in start until end) { val textLine = page.getLine(index)
break 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 ci++
end = boundary.next()
} }
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) { 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 { when {
relativePage > firstRelativePage -> { compare >= 0 -> {
curPage.selectStartMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) curPage.selectStartMoveIndex(relativePagePos, lineIndex, charIndex)
curPage.selectEndMoveIndex(relativePage, lineIndex, charIndex) curPage.selectEndMoveIndex(
} initialTextPos.relativePagePos,
relativePage < firstRelativePage -> { initialTextPos.lineIndex,
curPage.selectEndMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) initialTextPos.charIndex
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)
} }
else -> { else -> {
curPage.selectEndMoveIndex(firstRelativePage, firstLineIndex, firstCharIndex) curPage.selectStartMoveIndex(
curPage.selectStartMoveIndex(relativePage, lineIndex, charIndex) initialTextPos.relativePagePos,
initialTextPos.lineIndex,
initialTextPos.charIndex
)
curPage.selectEndMoveIndex(relativePagePos, lineIndex, charIndex)
} }
} }
} }

@ -1,21 +1,27 @@
package io.legado.app.ui.book.read.page.entities package io.legado.app.ui.book.read.page.entities
data class TextPos( data class TextPos(
var relativePos: Int, var relativePagePos: Int,
var lineIndex: Int, var lineIndex: Int,
var charIndex: 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) { fun upData(pos: TextPos) {
relativePos = pos.relativePos relativePagePos = pos.relativePagePos
lineIndex = pos.lineIndex lineIndex = pos.lineIndex
charIndex = pos.charIndex charIndex = pos.charIndex
} }
fun compare(pos: TextPos): Int { fun compare(pos: TextPos): Int {
return when { return when {
relativePos < pos.relativePos -> -3 relativePagePos < pos.relativePagePos -> -3
relativePos > pos.relativePos -> 3 relativePagePos > pos.relativePagePos -> 3
lineIndex < pos.lineIndex -> -2 lineIndex < pos.lineIndex -> -2
lineIndex > pos.lineIndex -> 2 lineIndex > pos.lineIndex -> 2
charIndex < pos.charIndex -> -1 charIndex < pos.charIndex -> -1
@ -23,4 +29,16 @@ data class TextPos(
else -> 0 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
}
}
} }
Loading…
Cancel
Save