This commit is contained in:
Horis
2023-09-24 11:42:21 +08:00
parent 2a6b0acd3a
commit be0faf93da
6 changed files with 213 additions and 81 deletions
@@ -605,19 +605,36 @@ class ReadBookActivity : BaseReadBookActivity(),
MotionEvent.ACTION_DOWN -> textActionMenu.dismiss() MotionEvent.ACTION_DOWN -> textActionMenu.dismiss()
MotionEvent.ACTION_MOVE -> { MotionEvent.ACTION_MOVE -> {
when (v.id) { when (v.id) {
R.id.cursor_left -> readView.curPage.selectStartMove( R.id.cursor_left -> if (!readView.curPage.getReverseStartCursor()) {
event.rawX + cursorLeft.width, readView.curPage.selectStartMove(
event.rawY - cursorLeft.height 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( R.id.cursor_right -> if (readView.curPage.getReverseEndCursor()) {
event.rawX - cursorRight.width, readView.curPage.selectStartMove(
event.rawY - cursorRight.height 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 return true
} }
@@ -55,6 +55,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} else { } else {
256 * 1024 * 1024 256 * 1024 * 1024
} }
var reverseStartCursor = false
var reverseEndCursor = false
//滚动参数 //滚动参数
private val pageFactory: TextPageFactory get() = callBack.pageFactory 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) { fun selectStartMove(x: Float, y: Float) {
touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn -> touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn ->
if (selectStart.compare(textPos) != 0) { if (selectStart.compare(textPos) == 0) {
if (textPos.compare(selectEnd) <= 0) { return@touchRough
selectStart.upData(pos = textPos)
upSelectedStart(
textColumn.start,
textLine.lineBottom + relativeOffset,
textLine.lineTop + relativeOffset
)
upSelectChars()
}
} }
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) { fun selectEndMove(x: Float, y: Float) {
touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn -> touchRough(x, y) { relativeOffset, textPos, _, textLine, textColumn ->
if (textPos.compare(selectEnd) != 0) { if (textPos.compare(selectEnd) == 0) {
if (textPos.compare(selectStart) >= 0) { return@touchRough
selectEnd.upData(textPos)
upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset)
upSelectChars()
}
} }
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 column: BaseColumn
) -> Unit ) -> Unit
) { ) {
if (!visibleRect.contains(x, y)) return
var relativeOffset: Float var relativeOffset: Float
for (relativePos in 0..2) { for (relativePos in 0..2) {
relativeOffset = relativeOffset(relativePos) relativeOffset = relativeOffset(relativePos)
@@ -483,10 +508,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
return 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( touched.invoke(
relativeOffset, relativeOffset,
TextPos(relativePos, lineIndex, charIndex), TextPos(relativePos, lineIndex, charIndex, false, isLast),
textPage, textLine, textColumn textPage, textLine, textColumn
) )
return 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.relativePagePos = relativePagePos
selectStart.lineIndex = lineIndex selectStart.lineIndex = lineIndex
selectStart.columnIndex = charIndex selectStart.columnIndex = charIndex
selectStart.isTouch = isTouch
selectStart.isLast = isLast
val textLine = relativePage(relativePagePos).getLine(lineIndex) val textLine = relativePage(relativePagePos).getLine(lineIndex)
val textColumn = textLine.getColumn(charIndex) val textColumn = textLine.getColumn(charIndex)
upSelectedStart( upSelectedStart(
@@ -559,19 +597,35 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
upSelectChars() 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.relativePagePos = relativePage
selectEnd.lineIndex = lineIndex selectEnd.lineIndex = lineIndex
selectEnd.columnIndex = charIndex selectEnd.columnIndex = charIndex
selectEnd.isTouch = isTouch
selectEnd.isLast = isLast
val textLine = relativePage(relativePage).getLine(lineIndex) val textLine = relativePage(relativePage).getLine(lineIndex)
val textColumn = textLine.getColumn(charIndex) val textColumn = textLine.getColumn(charIndex)
upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset(relativePage)) upSelectedEnd(textColumn.end, textLine.lineBottom + relativeOffset(relativePage))
upSelectChars() upSelectChars()
} }
fun selectEndMoveIndex(textPos: TextPos) = textPos.run {
selectEndMoveIndex(relativePagePos, lineIndex, columnIndex, isTouch, isLast)
}
private fun upSelectChars() { private fun upSelectChars() {
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)
@@ -583,8 +637,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
for ((charIndex, column) in textLine.columns.withIndex()) { for ((charIndex, column) in textLine.columns.withIndex()) {
textPos.columnIndex = charIndex textPos.columnIndex = charIndex
if (column is TextColumn) { if (column is TextColumn) {
column.selected = val compareStart = textPos.compare(selectStart)
textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0 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.isSearchResult =
column.selected && callBack.isSelectingSearchResult column.selected && callBack.isSelectingSearchResult
if (column.isSearchResult) { 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) { fun cancelSelect(clearSearchResult: Boolean = false) {
val last = if (callBack.isScroll) 2 else 0 val last = if (callBack.isScroll) 2 else 0
for (relativePos in 0..last) { for (relativePos in 0..last) {
@@ -641,16 +706,34 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
textPos.columnIndex = charIndex textPos.columnIndex = charIndex
val compareStart = textPos.compare(selectStart) val compareStart = textPos.compare(selectStart)
val compareEnd = textPos.compare(selectEnd) val compareEnd = textPos.compare(selectEnd)
if (compareStart >= 0 && compareEnd <= 0) { if (column is TextColumn) {
if (column is TextColumn) { when {
builder.append(column.charData) compareStart == 0 -> {
} if (selectStart.isTouch) {
if ( builder.append(column.charData)
textLine.isParagraphEnd }
&& charIndex == textLine.charSize - 1 if (
&& compareEnd != 0 textLine.isParagraphEnd
) { && charIndex == textLine.charSize - 1
builder.append("\n") && 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")
}
}
} }
} }
} }
@@ -365,16 +365,60 @@ class PageView(context: Context) : FrameLayout(context) {
binding.contentTextView.selectStartMove(x, y - headerHeight) binding.contentTextView.selectStartMove(x, y - headerHeight)
} }
fun selectStartMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { fun selectStartMoveIndex(
binding.contentTextView.selectStartMoveIndex(relativePagePos, lineIndex, charIndex) 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) { fun selectEndMove(x: Float, y: Float) {
binding.contentTextView.selectEndMove(x, y - headerHeight) binding.contentTextView.selectEndMove(x, y - headerHeight)
} }
fun selectEndMoveIndex(relativePagePos: Int, lineIndex: Int, charIndex: Int) { fun selectEndMoveIndex(
binding.contentTextView.selectEndMoveIndex(relativePagePos, lineIndex, charIndex) 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) { fun cancelSelect(clearSearchResult: Boolean = false) {
@@ -360,16 +360,8 @@ class ReadView(context: Context, attrs: AttributeSet) :
} }
} }
} }
curPage.selectStartMoveIndex( curPage.selectStartMoveIndex(startPos)
startPos.relativePagePos, curPage.selectEndMoveIndex(endPos)
startPos.lineIndex,
startPos.columnIndex
)
curPage.selectEndMoveIndex(
endPos.relativePagePos,
endPos.lineIndex,
endPos.columnIndex
)
} }
} }
} }
@@ -441,28 +433,12 @@ class ReadView(context: Context, attrs: AttributeSet) :
val compare = initialTextPos.compare(textPos) val compare = initialTextPos.compare(textPos)
when { when {
compare >= 0 -> { compare >= 0 -> {
curPage.selectStartMoveIndex( curPage.selectStartMoveIndex(textPos)
textPos.relativePagePos, curPage.selectEndMoveIndex(initialTextPos)
textPos.lineIndex,
textPos.columnIndex
)
curPage.selectEndMoveIndex(
initialTextPos.relativePagePos,
initialTextPos.lineIndex,
initialTextPos.columnIndex
)
} }
else -> { else -> {
curPage.selectStartMoveIndex( curPage.selectStartMoveIndex(initialTextPos)
initialTextPos.relativePagePos, curPage.selectEndMoveIndex(textPos)
initialTextPos.lineIndex,
initialTextPos.columnIndex
)
curPage.selectEndMoveIndex(
textPos.relativePagePos,
textPos.lineIndex,
textPos.columnIndex
)
} }
} }
} }
@@ -10,19 +10,31 @@ import androidx.annotation.Keep
data class TextPos( data class TextPos(
var relativePagePos: Int, var relativePagePos: Int,
var lineIndex: 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.relativePagePos = relativePos
this.lineIndex = lineIndex this.lineIndex = lineIndex
this.columnIndex = charIndex this.columnIndex = charIndex
this.isTouch = isTouch
this.isLast = isLast
} }
fun upData(pos: TextPos) { fun upData(pos: TextPos) {
relativePagePos = pos.relativePagePos relativePagePos = pos.relativePagePos
lineIndex = pos.lineIndex lineIndex = pos.lineIndex
columnIndex = pos.columnIndex columnIndex = pos.columnIndex
isTouch = pos.isTouch
isLast = pos.isLast
} }
fun compare(pos: TextPos): Int { fun compare(pos: TextPos): Int {
+3 -3
View File
@@ -378,7 +378,7 @@
<string name="behavior_main_t">Ocultar automáticamente la barra de herramientas</string> <string name="behavior_main_t">Ocultar automáticamente la barra de herramientas</string>
<string name="behavior_main_s">La barra de herramientas se ocultará automáticamente cuando deslice la Librería</string> <string name="behavior_main_s">La barra de herramientas se ocultará automáticamente cuando deslice la Librería</string>
<string name="login">Iniciar sesión</string> <string name="login">Iniciar sesión</string>
<string name="login_source">Iniciar sesión% s</string> <string name="login_source">Iniciar sesión %s</string>
<string name="success">Completado</string> <string name="success">Completado</string>
<string name="source_no_login">La fuente actual no se ha configurado con una dirección de inicio de sesión</string> <string name="source_no_login">La fuente actual no se ha configurado con una dirección de inicio de sesión</string>
<string name="no_prev_page">Sin página anterior</string> <string name="no_prev_page">Sin página anterior</string>
@@ -450,7 +450,7 @@
<string name="error_get_book_info">Error al obtener la información del libro</string> <string name="error_get_book_info">Error al obtener la información del libro</string>
<string name="error_get_content">Error al obtener el contenido</string> <string name="error_get_content">Error al obtener el contenido</string>
<string name="error_get_chapter_list">Error al obtener la lista de capítulos</string> <string name="error_get_chapter_list">Error al obtener la lista de capítulos</string>
<string name="error_get_web_content">Error al acceder al sitio:% s</string> <string name="error_get_web_content">Error al acceder al sitio: %s</string>
<string name="error_read_file">Error al leer el archivo</string> <string name="error_read_file">Error al leer el archivo</string>
<string name="error_load_toc">Error al cargar la lista de capítulos</string> <string name="error_load_toc">Error al cargar la lista de capítulos</string>
<string name="error_get_data">Error al obtener los datos</string> <string name="error_get_data">Error al obtener los datos</string>
@@ -812,7 +812,7 @@
<string name="export_bookshelf">Exportar lista de libros</string> <string name="export_bookshelf">Exportar lista de libros</string>
<string name="import_bookshelf">Importar lista de libros</string> <string name="import_bookshelf">Importar lista de libros</string>
<string name="pre_download">Descarga anterior</string> <string name="pre_download">Descarga anterior</string>
<string name="pre_download_s">Descargue% s capítulos antes</string> <string name="pre_download_s">Descargue %s capítulos antes</string>
<string name="is_enabled">Está habilitado</string> <string name="is_enabled">Está habilitado</string>
<string name="background_image">Imagen de fondo</string> <string name="background_image">Imagen de fondo</string>
<string name="copy_book_url">Copiar URL del libro</string> <string name="copy_book_url">Copiar URL del libro</string>