pull/1794/head
kunfei 2 years ago
parent 15ba7bda89
commit 6077e39013
  1. 207
      app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
  2. 2
      app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
  3. 2
      app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt
  4. 2
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt

@ -36,8 +36,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} }
private var callBack: CallBack private var callBack: CallBack
private val visibleRect = RectF() private val visibleRect = RectF()
private val selectStart = arrayOf(0, 0, 0) private val selectStart = Pos(0, 0, 0)
private val selectEnd = arrayOf(0, 0, 0) private val selectEnd = Pos(0, 0, 0)
var textPage: TextPage = TextPage() var textPage: TextPage = TextPage()
private set private set
@ -240,16 +240,10 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
*/ */
fun selectStartMove(x: Float, y: Float) { fun selectStartMove(x: Float, y: Float) {
touch(x, y) { relativePos, _, relativeOffset, lineIndex, textLine, charIndex, textChar -> touch(x, y) { relativePos, _, relativeOffset, lineIndex, textLine, charIndex, textChar ->
if (selectStart[0] != relativePos || val pos = Pos(relativePos, lineIndex, charIndex)
selectStart[1] != lineIndex || if (selectStart.compare(pos) != 0) {
selectStart[2] != charIndex if (pos.compare(selectEnd) <= 0) {
) { selectStart.upData(pos = pos)
if (selectToInt(relativePos, lineIndex, charIndex)
<= selectToInt(selectEnd)
) {
selectStart[0] = relativePos
selectStart[1] = lineIndex
selectStart[2] = charIndex
upSelectedStart( upSelectedStart(
textChar.start, textChar.start,
textLine.lineBottom + relativeOffset, textLine.lineBottom + relativeOffset,
@ -266,16 +260,10 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
*/ */
fun selectEndMove(x: Float, y: Float) { fun selectEndMove(x: Float, y: Float) {
touch(x, y) { relativePos, _, relativeOffset, lineIndex, textLine, charIndex, textChar -> touch(x, y) { relativePos, _, relativeOffset, lineIndex, textLine, charIndex, textChar ->
if (selectEnd[0] != relativePos val pos = Pos(relativePos, lineIndex, charIndex)
|| selectEnd[1] != lineIndex if (pos.compare(selectEnd) != 0) {
|| selectEnd[2] != charIndex if (pos.compare(selectStart) >= 0) {
) { selectEnd.upData(pos)
if (selectToInt(relativePos, lineIndex, charIndex)
>= selectToInt(selectStart)
) {
selectEnd[0] = relativePos
selectEnd[1] = lineIndex
selectEnd[2] = charIndex
upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset) upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset)
upSelectChars() upSelectChars()
} }
@ -329,9 +317,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
* 选择开始文字 * 选择开始文字
*/ */
fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { fun selectStartMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) {
selectStart[0] = relativePage selectStart.relativePos = relativePage
selectStart[1] = lineIndex selectStart.lineIndex = lineIndex
selectStart[2] = charIndex selectStart.charIndex = charIndex
val textLine = relativePage(relativePage).getLine(lineIndex) val textLine = relativePage(relativePage).getLine(lineIndex)
val textChar = textLine.getTextChar(charIndex) val textChar = textLine.getTextChar(charIndex)
upSelectedStart( upSelectedStart(
@ -346,9 +334,9 @@ 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[0] = relativePage selectEnd.relativePos = relativePage
selectEnd[1] = lineIndex selectEnd.lineIndex = lineIndex
selectEnd[2] = charIndex selectEnd.charIndex = charIndex
val textLine = relativePage(relativePage).getLine(lineIndex) val textLine = relativePage(relativePage).getLine(lineIndex)
val textChar = textLine.getTextChar(charIndex) val textChar = textLine.getTextChar(charIndex)
upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset(relativePage)) upSelectedEnd(textChar.end, textLine.lineBottom + relativeOffset(relativePage))
@ -357,35 +345,13 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
private fun upSelectChars() { private fun upSelectChars() {
val last = if (callBack.isScroll) 2 else 0 val last = if (callBack.isScroll) 2 else 0
val charPos = Pos(0, 0, 0)
for (relativePos in 0..last) { for (relativePos in 0..last) {
for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) { for ((lineIndex, textLine) in relativePage(relativePos).textLines.withIndex()) {
for ((charIndex, textChar) in textLine.textChars.withIndex()) { for ((charIndex, textChar) in textLine.textChars.withIndex()) {
textChar.selected = when { charPos.upData(relativePos, lineIndex, charIndex)
relativePos == selectStart[0] textChar.selected =
&& relativePos == selectEnd[0] charPos.compare(selectStart) >= 0 && charPos.compare(selectEnd) <= 0
&& lineIndex == selectStart[1]
&& lineIndex == selectEnd[1] -> {
charIndex in selectStart[2]..selectEnd[2]
}
relativePos == selectStart[0] && lineIndex == selectStart[1] -> {
charIndex >= selectStart[2]
}
relativePos == selectEnd[0] && lineIndex == selectEnd[1] -> {
charIndex <= selectEnd[2]
}
relativePos == selectStart[0] && relativePos == selectEnd[0] -> {
lineIndex in (selectStart[1] + 1) until selectEnd[1]
}
relativePos == selectStart[0] -> {
lineIndex > selectStart[1]
}
relativePos == selectEnd[0] -> {
lineIndex < selectEnd[1]
}
else -> {
relativePos in selectStart[0] + 1 until selectEnd[0]
}
}
textChar.isSearchResult = textChar.selected && callBack.isSelectingSearchResult textChar.isSearchResult = textChar.selected && callBack.isSelectingSearchResult
} }
} }
@ -414,103 +380,51 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
callBack.onCancelSelect() callBack.onCancelSelect()
} }
val selectedText: String fun getSelectedText(): String {
get() { val pos = Pos(0, 0, 0)
val stringBuilder = StringBuilder() val builder = StringBuilder()
for (relativePos in selectStart[0]..selectEnd[0]) { for (relativePos in selectStart.relativePos..selectEnd.relativePos) {
val textPage = relativePage(relativePos) val textPage = relativePage(relativePos)
when { pos.relativePos = relativePos
relativePos == selectStart[0] && relativePos == selectEnd[0] -> { textPage.textLines.forEachIndexed { lineIndex, textLine ->
for (lineIndex in selectStart[1]..selectEnd[1]) { pos.lineIndex = lineIndex
when { textLine.textChars.forEachIndexed { charIndex, textChar ->
lineIndex == selectStart[1] && lineIndex == selectEnd[1] -> { pos.charIndex = charIndex
stringBuilder.append( if (pos.compare(selectStart) >= 0
textPage.textLines[lineIndex].text && pos.compare(selectEnd) <= 0
.substring(selectStart[2], selectEnd[2] + 1) ) {
) builder.append(textChar.charData)
} if (charIndex == textLine.charSize - 1
lineIndex == selectStart[1] -> { && textLine.text.endsWith("\n")
stringBuilder.append( ) {
textPage.textLines[lineIndex].text builder.append("\n")
.substring(selectStart[2])
)
}
lineIndex == selectEnd[1] -> {
stringBuilder.append(
textPage.textLines[lineIndex].text
.substring(0, selectEnd[2] + 1)
)
}
else -> {
stringBuilder.append(textPage.textLines[lineIndex].text)
}
}
}
}
relativePos == selectStart[0] -> {
for (lineIndex in selectStart[1] until textPage.textLines.size) {
when (lineIndex) {
selectStart[1] -> {
stringBuilder.append(
textPage.textLines[lineIndex].text
.substring(selectStart[2])
)
}
else -> {
stringBuilder.append(textPage.textLines[lineIndex].text)
}
}
}
}
relativePos == selectEnd[0] -> {
for (lineIndex in 0..selectEnd[1]) {
when (lineIndex) {
selectEnd[1] -> {
stringBuilder.append(
textPage.textLines[lineIndex].text
.substring(0, selectEnd[2] + 1)
)
}
else -> {
stringBuilder.append(textPage.textLines[lineIndex].text)
}
}
}
}
relativePos in selectStart[0] + 1 until selectEnd[0] -> {
for (lineIndex in selectStart[1]..selectEnd[1]) {
stringBuilder.append(textPage.textLines[lineIndex].text)
} }
} }
} }
} }
return stringBuilder.toString()
} }
if (builder.endsWith("\n")) {
return builder.substring(0, builder.lastIndex)
}
return builder.toString()
}
fun createBookmark(): Bookmark? { fun createBookmark(): Bookmark? {
val page = relativePage(selectStart[0]) val page = relativePage(selectStart.relativePos)
page.getTextChapter()?.let { chapter -> page.getTextChapter()?.let { chapter ->
ReadBook.book?.let { book -> ReadBook.book?.let { book ->
return book.createBookMark().apply { return book.createBookMark().apply {
chapterIndex = page.chapterIndex chapterIndex = page.chapterIndex
chapterPos = chapter.getReadLength(page.index) + chapterPos = chapter.getReadLength(page.index) +
page.getSelectStartLength(selectStart[1], selectStart[2]) page.getSelectStartLength(selectStart.lineIndex, selectStart.charIndex)
chapterName = chapter.title chapterName = chapter.title
bookText = selectedText bookText = getSelectedText()
} }
} }
} }
return null return null
} }
private fun selectToInt(page: Int, line: Int, char: Int): Int {
return page * 10000000 + line * 100000 + char
}
private fun selectToInt(select: Array<Int>): Int {
return select[0] * 10000000 + select[1] * 100000 + select[2]
}
private fun relativeOffset(relativePos: Int): Float { private fun relativeOffset(relativePos: Int): Float {
return when (relativePos) { return when (relativePos) {
0 -> pageOffset.toFloat() 0 -> pageOffset.toFloat()
@ -527,6 +441,35 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} }
} }
private data class Pos(
var relativePos: Int,
var lineIndex: Int,
var charIndex: Int
) {
fun upData(relativePos: Int, lineIndex: Int, charIndex: Int) {
this.relativePos = relativePos
this.lineIndex = lineIndex
this.charIndex = charIndex
}
fun upData(pos: Pos) {
relativePos = pos.relativePos
lineIndex = pos.lineIndex
charIndex = pos.charIndex
}
fun compare(pos: Pos): Int {
if (relativePos < pos.relativePos) return -1
if (relativePos > pos.relativePos) return 1
if (lineIndex < pos.lineIndex) return -1
if (lineIndex > pos.lineIndex) return 1
if (charIndex < pos.charIndex) return -1
if (charIndex > pos.charIndex) return 1
return 0
}
}
interface CallBack { interface CallBack {
fun upSelectedStart(x: Float, y: Float, top: Float) fun upSelectedStart(x: Float, y: Float, top: Float)
fun upSelectedEnd(x: Float, y: Float) fun upSelectedEnd(x: Float, y: Float)

@ -295,7 +295,7 @@ class PageView(context: Context) : FrameLayout(context) {
return binding.contentTextView.relativePage(relativePos) return binding.contentTextView.relativePage(relativePos)
} }
val selectedText: String get() = binding.contentTextView.selectedText val selectedText: String get() = binding.contentTextView.getSelectedText()
val textPage get() = binding.contentTextView.textPage val textPage get() = binding.contentTextView.textPage
} }

@ -276,7 +276,7 @@ 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) { relativePage, lineIndex, charIndex ->
val page = if (isScroll) curPage.relativePage(relativePage) else curPage.textPage val page = curPage.relativePage(relativePage)
with(page) { with(page) {
isTextSelected = true isTextSelected = true
firstRelativePage = relativePage firstRelativePage = relativePage

@ -4,7 +4,7 @@ import android.text.TextPaint
import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.textHeight import io.legado.app.utils.textHeight
@Suppress("unused") @Suppress("unused", "MemberVisibilityCanBePrivate")
data class TextLine( data class TextLine(
var text: String = "", var text: String = "",
val textChars: ArrayList<TextChar> = arrayListOf(), val textChars: ArrayList<TextChar> = arrayListOf(),

Loading…
Cancel
Save