diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index 88ec1cf35..48f1aab97 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -605,19 +605,36 @@ class ReadBookActivity : BaseReadBookActivity(), MotionEvent.ACTION_DOWN -> textActionMenu.dismiss() MotionEvent.ACTION_MOVE -> { when (v.id) { - R.id.cursor_left -> readView.curPage.selectStartMove( - event.rawX + cursorLeft.width, - event.rawY - cursorLeft.height - ) + R.id.cursor_left -> if (!readView.curPage.getReverseStartCursor()) { + readView.curPage.selectStartMove( + event.rawX + cursorLeft.width, + event.rawY - cursorLeft.height + ) + } else { + readView.curPage.selectEndMove( + event.rawX - cursorRight.width, + event.rawY - cursorRight.height + ) + } - R.id.cursor_right -> readView.curPage.selectEndMove( - event.rawX - cursorRight.width, - event.rawY - cursorRight.height - ) + R.id.cursor_right -> if (readView.curPage.getReverseEndCursor()) { + readView.curPage.selectStartMove( + event.rawX + cursorLeft.width, + event.rawY - cursorLeft.height + ) + } else { + readView.curPage.selectEndMove( + event.rawX - cursorRight.width, + event.rawY - cursorRight.height + ) + } } } - MotionEvent.ACTION_UP -> showTextActionMenu() + MotionEvent.ACTION_UP -> { + readView.curPage.resetReverseCursor() + showTextActionMenu() + } } return true } 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 0a5cdb78d..1d5541164 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 @@ -55,6 +55,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } else { 256 * 1024 * 1024 } + var reverseStartCursor = false + var reverseEndCursor = false //滚动参数 private val pageFactory: TextPageFactory get() = callBack.pageFactory @@ -373,17 +375,27 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at */ fun selectStartMove(x: Float, y: Float) { touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn -> - if (selectStart.compare(textPos) != 0) { - if (textPos.compare(selectEnd) <= 0) { - selectStart.upData(pos = textPos) - upSelectedStart( - textColumn.start, - textLine.lineBottom + relativeOffset, - textLine.lineTop + relativeOffset - ) - upSelectChars() - } + if (selectStart.compare(textPos) == 0) { + return@touchRough } + if (textPos.compare(selectEnd) <= 0) { + selectStart.upData(pos = textPos) + upSelectedStart( + if (textPos.isTouch) textColumn.start else textColumn.end, + textLine.lineBottom + relativeOffset, + textLine.lineTop + relativeOffset + ) + } else { + reverseStartCursor = true + reverseEndCursor = false + selectStartMoveIndex(selectEnd) + selectEnd.upData(textPos) + upSelectedEnd( + if (selectEnd.isTouch || selectEnd.isLast) textColumn.end else textColumn.start, + textLine.lineBottom + relativeOffset + ) + } + upSelectChars() } } @@ -392,13 +404,27 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at */ fun selectEndMove(x: Float, y: Float) { touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn -> - if (textPos.compare(selectEnd) != 0) { - if (textPos.compare(selectStart) >= 0) { - selectEnd.upData(textPos) - upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset) - upSelectChars() - } + if (textPos.compare(selectEnd) == 0) { + return@touchRough } + if (textPos.compare(selectStart) >= 0) { + selectEnd.upData(textPos) + upSelectedEnd( + if (selectEnd.isTouch || selectEnd.isLast) textColumn.end else textColumn.start, + textLine.lineBottom + relativeOffset + ) + } else { + reverseEndCursor = true + reverseStartCursor = false + selectEndMoveIndex(selectStart) + selectStart.upData(textPos) + upSelectedStart( + if (textPos.isTouch) textColumn.start else textColumn.end, + textLine.lineBottom + relativeOffset, + textLine.lineTop + relativeOffset + ) + } + upSelectChars() } } @@ -461,7 +487,6 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at column: BaseColumn ) -> Unit ) { - if (!visibleRect.contains(x, y)) return var relativeOffset: Float for (relativePos in 0..2) { relativeOffset = relativeOffset(relativePos) @@ -483,10 +508,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at return } } - val (charIndex, textColumn) = textLine.columns.withIndex().last() + val isLast = textLine.columns.first().start < x + val (charIndex, textColumn) = if (isLast) { + textLine.columns.withIndex().last() + } else { + textLine.columns.withIndex().first() + } touched.invoke( relativeOffset, - TextPos(relativePos, lineIndex, charIndex), + TextPos(relativePos, lineIndex, charIndex, false, isLast), textPage, textLine, textColumn ) return @@ -545,10 +575,18 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at /** * 选择开始文字 */ - fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { + fun selectStartMoveIndex( + relativePagePos: Int, + lineIndex: Int, + charIndex: Int, + isTouch: Boolean, + isLast: Boolean = false + ) { selectStart.relativePagePos = relativePagePos selectStart.lineIndex = lineIndex selectStart.columnIndex = charIndex + selectStart.isTouch = isTouch + selectStart.isLast = isLast val textLine = relativePage(relativePagePos).getLine(lineIndex) val textColumn = textLine.getColumn(charIndex) upSelectedStart( @@ -559,19 +597,35 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at upSelectChars() } + fun selectStartMoveIndex(textPos: TextPos) = textPos.run { + selectStartMoveIndex(relativePagePos, lineIndex, columnIndex, isTouch, isLast) + } + /** * 选择结束文字 */ - fun selectEndMoveIndex(relativePage: Int, lineIndex: Int, charIndex: Int) { + fun selectEndMoveIndex( + relativePage: Int, + lineIndex: Int, + charIndex: Int, + isTouch: Boolean, + isLast: Boolean = false + ) { selectEnd.relativePagePos = relativePage selectEnd.lineIndex = lineIndex selectEnd.columnIndex = charIndex + selectEnd.isTouch = isTouch + selectEnd.isLast = isLast val textLine = relativePage(relativePage).getLine(lineIndex) val textColumn = textLine.getColumn(charIndex) upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset(relativePage)) upSelectChars() } + fun selectEndMoveIndex(textPos: TextPos) = textPos.run { + selectEndMoveIndex(relativePagePos, lineIndex, columnIndex, isTouch, isLast) + } + private fun upSelectChars() { val last = if (callBack.isScroll) 2 else 0 val textPos = TextPos(0, 0, 0) @@ -583,8 +637,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at for ((charIndex, column) in textLine.columns.withIndex()) { textPos.columnIndex = charIndex if (column is TextColumn) { - column.selected = - textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0 + val compareStart = textPos.compare(selectStart) + val compareEnd = textPos.compare(selectEnd) + column.selected = when { + compareStart == 0 -> selectStart.isTouch + compareEnd == 0 -> selectEnd.isTouch || selectEnd.isLast + compareStart > 0 && compareEnd < 0 -> true + else -> false + } column.isSearchResult = column.selected && callBack.isSelectingSearchResult if (column.isSearchResult) { @@ -609,6 +669,11 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at } } + fun resetReverseCursor() { + reverseStartCursor = false + reverseEndCursor = false + } + fun cancelSelect(clearSearchResult: Boolean = false) { val last = if (callBack.isScroll) 2 else 0 for (relativePos in 0..last) { @@ -641,16 +706,34 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at textPos.columnIndex = charIndex val compareStart = textPos.compare(selectStart) val compareEnd = textPos.compare(selectEnd) - if (compareStart >= 0 && compareEnd <= 0) { - if (column is TextColumn) { - builder.append(column.charData) - } - if ( - textLine.isParagraphEnd - && charIndex == textLine.charSize - 1 - && compareEnd != 0 - ) { - builder.append("\n") + if (column is TextColumn) { + when { + compareStart == 0 -> { + if (selectStart.isTouch) { + builder.append(column.charData) + } + if ( + textLine.isParagraphEnd + && charIndex == textLine.charSize - 1 + && compareEnd != 0 + ) { + builder.append("\n") + } + } + + compareEnd == 0 -> if (selectEnd.isTouch || selectEnd.isLast) { + builder.append(column.charData) + } + + compareStart > 0 && compareEnd < 0 -> { + builder.append(column.charData) + if ( + textLine.isParagraphEnd + && charIndex == textLine.charSize - 1 + ) { + builder.append("\n") + } + } } } } 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 d61a55df8..353b71a6a 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 @@ -365,16 +365,60 @@ class PageView(context: Context) : FrameLayout(context) { binding.contentTextView.selectStartMove(x, y - headerHeight) } - fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { - binding.contentTextView.selectStartMoveIndex(relativePagePos, lineIndex, charIndex) + fun selectStartMoveIndex( + relativePagePos: Int, + lineIndex: Int, + charIndex: Int, + isTouch: Boolean = true, + isLast: Boolean = false + ) { + binding.contentTextView.selectStartMoveIndex( + relativePagePos, + lineIndex, + charIndex, + isTouch, + isLast + ) + } + + fun selectStartMoveIndex(textPos: TextPos) { + binding.contentTextView.selectStartMoveIndex(textPos) } fun selectEndMove(x: Float, y: Float) { binding.contentTextView.selectEndMove(x, y - headerHeight) } - fun selectEndMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { - binding.contentTextView.selectEndMoveIndex(relativePagePos, lineIndex, charIndex) + fun selectEndMoveIndex( + relativePagePos: Int, + lineIndex: Int, + charIndex: Int, + isTouch: Boolean = true, + isLast: Boolean = false + ) { + binding.contentTextView.selectEndMoveIndex( + relativePagePos, + lineIndex, + charIndex, + isTouch, + isLast + ) + } + + fun selectEndMoveIndex(textPos: TextPos) { + binding.contentTextView.selectEndMoveIndex(textPos) + } + + fun getReverseStartCursor(): Boolean { + return binding.contentTextView.reverseStartCursor + } + + fun getReverseEndCursor(): Boolean { + return binding.contentTextView.reverseEndCursor + } + + fun resetReverseCursor() { + binding.contentTextView.resetReverseCursor() } fun cancelSelect(clearSearchResult: Boolean = false) { 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 7d5110f41..5a252d487 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 @@ -360,16 +360,8 @@ class ReadView(context: Context, attrs: AttributeSet) : } } } - curPage.selectStartMoveIndex( - startPos.relativePagePos, - startPos.lineIndex, - startPos.columnIndex - ) - curPage.selectEndMoveIndex( - endPos.relativePagePos, - endPos.lineIndex, - endPos.columnIndex - ) + curPage.selectStartMoveIndex(startPos) + curPage.selectEndMoveIndex(endPos) } } } @@ -441,28 +433,12 @@ class ReadView(context: Context, attrs: AttributeSet) : val compare = initialTextPos.compare(textPos) when { compare >= 0 -> { - curPage.selectStartMoveIndex( - textPos.relativePagePos, - textPos.lineIndex, - textPos.columnIndex - ) - curPage.selectEndMoveIndex( - initialTextPos.relativePagePos, - initialTextPos.lineIndex, - initialTextPos.columnIndex - ) + curPage.selectStartMoveIndex(textPos) + curPage.selectEndMoveIndex(initialTextPos) } else -> { - curPage.selectStartMoveIndex( - initialTextPos.relativePagePos, - initialTextPos.lineIndex, - initialTextPos.columnIndex - ) - curPage.selectEndMoveIndex( - textPos.relativePagePos, - textPos.lineIndex, - textPos.columnIndex - ) + curPage.selectStartMoveIndex(initialTextPos) + curPage.selectEndMoveIndex(textPos) } } } 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 d8ec877d0..cb8b374b3 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 @@ -10,19 +10,31 @@ import androidx.annotation.Keep data class TextPos( var relativePagePos: Int, var lineIndex: Int, - var columnIndex: Int + var columnIndex: Int, + var isTouch: Boolean = true, + var isLast: Boolean = false ) { - fun upData(relativePos: Int, lineIndex: Int, charIndex: Int) { + fun upData( + relativePos: Int, + lineIndex: Int, + charIndex: Int, + isTouch: Boolean, + isLast: Boolean + ) { this.relativePagePos = relativePos this.lineIndex = lineIndex this.columnIndex = charIndex + this.isTouch = isTouch + this.isLast = isLast } fun upData(pos: TextPos) { relativePagePos = pos.relativePagePos lineIndex = pos.lineIndex columnIndex = pos.columnIndex + isTouch = pos.isTouch + isLast = pos.isLast } fun compare(pos: TextPos): Int { diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 0c4321831..1ebf494cc 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -378,7 +378,7 @@ Ocultar automáticamente la barra de herramientas La barra de herramientas se ocultará automáticamente cuando deslice la Librería Iniciar sesión - Iniciar sesión% s + Iniciar sesión %s Completado La fuente actual no se ha configurado con una dirección de inicio de sesión Sin página anterior @@ -450,7 +450,7 @@ Error al obtener la información del libro Error al obtener el contenido Error al obtener la lista de capítulos - Error al acceder al sitio:% s + Error al acceder al sitio: %s Error al leer el archivo Error al cargar la lista de capítulos Error al obtener los datos @@ -812,7 +812,7 @@ Exportar lista de libros Importar lista de libros Descarga anterior - Descargue% s capítulos antes + Descargue %s capítulos antes Está habilitado Imagen de fondo Copiar URL del libro