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

@ -295,7 +295,7 @@ class PageView(context: Context) : FrameLayout(context) {
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
}

@ -276,7 +276,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
private fun onLongPress() {
kotlin.runCatching {
curPage.selectText(startX, startY) { relativePage, lineIndex, charIndex ->
val page = if (isScroll) curPage.relativePage(relativePage) else curPage.textPage
val page = curPage.relativePage(relativePage)
with(page) {
isTextSelected = true
firstRelativePage = relativePage

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

Loading…
Cancel
Save