pull/2268/head
kunfei 2 years ago
parent f9d3161d1a
commit 4f32cf0566
  1. 161
      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/entities/BaseColumn.kt
  3. 8
      app/src/main/java/io/legado/app/ui/book/read/page/entities/ImageColumn.kt
  4. 83
      app/src/main/java/io/legado/app/ui/book/read/page/entities/ReviewColumn.kt
  5. 11
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextColumn.kt
  6. 11
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt
  7. 6
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
  8. 24
      app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt

@ -4,7 +4,6 @@ import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.text.StaticLayout
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
@ -16,10 +15,7 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.lib.theme.accentColor
import io.legado.app.model.ReadBook
import io.legado.app.ui.book.read.page.entities.TextColumn
import io.legado.app.ui.book.read.page.entities.TextLine
import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.ui.book.read.page.entities.TextPos
import io.legado.app.ui.book.read.page.entities.*
import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.ui.book.read.page.provider.ImageProvider
import io.legado.app.ui.book.read.page.provider.TextPageFactory
@ -168,86 +164,19 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
reviewCountPaint.textSize = textPaint.textSize * 0.6F
reviewCountPaint.color = textColor
textLine.columns.forEach {
when (it.style) {
0 -> {
when (it) {
is TextColumn -> {
textPaint.color = textColor
if (it.isSearchResult) {
textPaint.color = context.accentColor
}
canvas.drawText(it.charData, it.start, lineBase, textPaint)
if (it.selected) {
canvas.drawRect(it.start, lineTop, it.end, lineBottom, selectedPaint)
}
}
1 -> drawImage(canvas, textPage, textLine, it, lineTop, lineBottom)
2 -> {
if (textLine.reviewCount <= 0) return@forEach
canvas.drawLine(
it.start,
lineBase - textPaint.textSize * 2 / 5,
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize / 4,
linePaint
)
canvas.drawLine(
it.start,
lineBase - textPaint.textSize * 0.38F,
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize * 0.55F,
linePaint
)
canvas.drawLine(
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize / 4,
it.start + textPaint.textSize / 6,
lineBase,
linePaint
)
canvas.drawLine(
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize * 0.55F,
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize * 0.8F,
linePaint
)
canvas.drawLine(
it.start + textPaint.textSize / 6,
lineBase,
it.start + textPaint.textSize * 1.6F,
lineBase,
linePaint
)
canvas.drawLine(
it.start + textPaint.textSize / 6,
lineBase - textPaint.textSize * 0.8F,
it.start + textPaint.textSize * 1.6F,
lineBase - textPaint.textSize * 0.8F,
linePaint
)
canvas.drawLine(
it.start + textPaint.textSize * 1.6F,
lineBase - textPaint.textSize * 0.8F,
it.start + textPaint.textSize * 1.6F,
lineBase,
linePaint
)
if (textLine.reviewCount < 100) canvas.drawText(
textLine.reviewCount.toString(),
it.start + textPaint.textSize * 0.87F -
StaticLayout.getDesiredWidth(
textLine.reviewCount.toString(),
reviewCountPaint
) / 2,
lineBase - textPaint.textSize / 6,
reviewCountPaint
)
else canvas.drawText(
"99+",
it.start + textPaint.textSize * 0.35F,
lineBase - textPaint.textSize / 6,
reviewCountPaint
)
}
}
if (it.selected) {
canvas.drawRect(it.start, lineTop, it.end, lineBottom, selectedPaint)
is ImageColumn -> drawImage(canvas, textPage, textLine, it, lineTop, lineBottom)
is ReviewColumn -> it.drawToCanvas(canvas, linePaint, reviewCountPaint, lineBase)
}
}
}
@ -260,7 +189,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
canvas: Canvas,
textPage: TextPage,
textLine: TextLine,
textColumn: TextColumn,
column: ImageColumn,
lineTop: Float,
lineBottom: Float
) {
@ -278,7 +207,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
isVisible &&
!cacheIncreased &&
ImageProvider.isTriggerRecycled() &&
!ImageProvider.isImageAlive(book, textColumn.charData)
!ImageProvider.isImageAlive(book, column.src)
) {
val newSize = ImageProvider.bitmapLruCache.maxSize() + increaseSize
if (newSize < maxCacheSize) {
@ -290,8 +219,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
}
val bitmap = ImageProvider.getImage(
book,
textColumn.charData,
(textColumn.end - textColumn.start).toInt(),
column.src,
(column.end - column.start).toInt(),
(lineBottom - lineTop).toInt()
) {
if (!drawVisibleImageOnly && isVisible) {
@ -301,12 +230,12 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} ?: return
val rectF = if (textLine.isImage) {
RectF(textColumn.start, lineTop, textColumn.end, lineBottom)
RectF(column.start, lineTop, column.end, lineBottom)
} else {
/*以宽度为基准保持图片的原始比例叠加,当div为负数时,允许高度比字符更高*/
val h = (textColumn.end - textColumn.start) / bitmap.width * bitmap.height
val h = (column.end - column.start) / bitmap.width * bitmap.height
val div = (lineBottom - lineTop - h) / 2
RectF(textColumn.start, lineTop + div, textColumn.end, lineBottom - div)
RectF(column.start, lineTop + div, column.end, lineBottom - div)
}
kotlin.runCatching {
canvas.drawBitmap(bitmap, null, rectF, imagePaint)
@ -360,15 +289,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
y: Float,
select: (textPos: TextPos) -> Unit,
) {
touch(x, y) { _, textPos, _, _, textColumn ->
if (textColumn.style == 2) return@touch
if (textColumn.style == 1) {
callBack.onImageLongPress(x, y, textColumn.charData)
} else {
if (!selectAble) return@touch
textColumn.selected = true
invalidate()
select(textPos)
touch(x, y) { _, textPos, _, _, column ->
when (column) {
is ImageColumn -> callBack.onImageLongPress(x, y, column.src)
is TextColumn -> {
if (!selectAble) return@touch
column.selected = true
invalidate()
select(textPos)
}
}
}
}
@ -379,8 +308,8 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
*/
fun click(x: Float, y: Float): Boolean {
var handled = false
touch(x, y) { _, textPos, textPage, textLine, textColumn ->
if (textColumn.style == 2) {
touch(x, y) { _, textPos, textPage, textLine, column ->
if (column is ReviewColumn) {
context.toastOnUi("Button Pressed!")
handled = true
}
@ -396,11 +325,12 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
y: Float,
select: (textPos: TextPos) -> Unit,
) {
touch(x, y) { _, textPos, _, _, textColumn ->
if (textColumn.style == 2) return@touch
textColumn.selected = true
invalidate()
select(textPos)
touch(x, y) { _, textPos, _, _, column ->
if (column is TextColumn) {
column.selected = true
invalidate()
select(textPos)
}
}
}
@ -450,7 +380,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
textPos: TextPos,
textPage: TextPage,
textLine: TextLine,
textColumn: TextColumn
column: BaseColumn
) -> Unit
) {
if (!visibleRect.contains(x, y)) return
@ -518,13 +448,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
textPos.relativePagePos = relativePos
for ((lineIndex, textLine) in relativePage(relativePos).lines.withIndex()) {
textPos.lineIndex = lineIndex
for ((charIndex, textColumn) in textLine.columns.withIndex()) {
for ((charIndex, column) in textLine.columns.withIndex()) {
textPos.charIndex = charIndex
if (textColumn.style == 2) continue
textColumn.selected =
textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0
textColumn.isSearchResult =
textColumn.selected && callBack.isSelectingSearchResult
if (column is TextColumn) {
column.selected =
textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0
column.isSearchResult =
column.selected && callBack.isSelectingSearchResult
}
}
}
}
@ -544,8 +475,10 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
for (relativePos in 0..last) {
relativePage(relativePos).lines.forEach { textLine ->
textLine.columns.forEach {
it.selected = false
if (fromSearchExit) it.isSearchResult = false
if (it is TextColumn) {
it.selected = false
if (fromSearchExit) it.isSearchResult = false
}
}
}
}
@ -561,12 +494,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
textPos.relativePagePos = relativePos
textPage.lines.forEachIndexed { lineIndex, textLine ->
textPos.lineIndex = lineIndex
textLine.columns.forEachIndexed { charIndex, textColumn ->
textLine.columns.forEachIndexed { charIndex, column ->
textPos.charIndex = charIndex
val compareStart = textPos.compare(selectStart)
val compareEnd = textPos.compare(selectEnd)
if (compareStart >= 0 && compareEnd <= 0) {
builder.append(textColumn.charData)
if (column is TextColumn) {
builder.append(column.charData)
}
if (
textLine.isParagraphEnd
&& charIndex == textLine.charSize - 1

@ -0,0 +1,14 @@
package io.legado.app.ui.book.read.page.entities
/**
* 列基类
*/
interface BaseColumn {
var start: Float
var end: Float
fun isTouch(x: Float): Boolean {
return x > start && x < end
}
}

@ -0,0 +1,8 @@
package io.legado.app.ui.book.read.page.entities
data class ImageColumn(
override var start: Float,
override var end: Float,
var src: String
) : BaseColumn {
}

@ -0,0 +1,83 @@
package io.legado.app.ui.book.read.page.entities
import android.graphics.Canvas
import android.graphics.Paint
import android.text.StaticLayout
import android.text.TextPaint
data class ReviewColumn(
override var start: Float,
override var end: Float,
var count: Int = 0
) : BaseColumn {
fun getCountText(): String {
if (count > 99) {
return "99+"
}
return count.toString()
}
fun drawToCanvas(canvas: Canvas, paint: Paint, countPaint: TextPaint, y: Float) {
if (count == 0) return
canvas.drawLine(
start,
y - paint.textSize * 2 / 5,
start + paint.textSize / 6,
y - paint.textSize / 4,
paint
)
canvas.drawLine(
start,
y - paint.textSize * 0.38F,
start + paint.textSize / 6,
y - paint.textSize * 0.55F,
paint
)
canvas.drawLine(
start + paint.textSize / 6,
y - paint.textSize / 4,
start + paint.textSize / 6,
y,
paint
)
canvas.drawLine(
start + paint.textSize / 6,
y - paint.textSize * 0.55F,
start + paint.textSize / 6,
y - paint.textSize * 0.8F,
paint
)
canvas.drawLine(
start + paint.textSize / 6,
y,
start + paint.textSize * 1.6F,
y,
paint
)
canvas.drawLine(
start + paint.textSize / 6,
y - paint.textSize * 0.8F,
start + paint.textSize * 1.6F,
y - paint.textSize * 0.8F,
paint
)
canvas.drawLine(
start + paint.textSize * 1.6F,
y - paint.textSize * 0.8F,
start + paint.textSize * 1.6F,
y,
paint
)
val text = getCountText()
val textWidth = StaticLayout.getDesiredWidth(getCountText(), countPaint)
canvas.drawText(
text,
start + paint.textSize * 0.87F - textWidth / 2,
y - paint.textSize / 6,
countPaint
)
}
}

@ -4,16 +4,11 @@ package io.legado.app.ui.book.read.page.entities
* 字符信息
*/
data class TextColumn(
override var start: Float,
override var end: Float,
val charData: String,
var start: Float,
var end: Float,
val style: Int = 0, //0:文字,1:图片,2:按钮
var selected: Boolean = false,
var isSearchResult: Boolean = false
) {
fun isTouch(x: Float): Boolean {
return x > start && x < end
}
) : BaseColumn {
}

@ -10,8 +10,7 @@ import io.legado.app.utils.textHeight
@Suppress("unused", "MemberVisibilityCanBePrivate")
data class TextLine(
var text: String = "",
private val textColumns: ArrayList<TextColumn> = arrayListOf(),
val reviewCount: Int = 0,
private val textColumns: ArrayList<BaseColumn> = arrayListOf(),
var lineTop: Float = 0f,
var lineBase: Float = 0f,
var lineBottom: Float = 0f,
@ -21,22 +20,22 @@ data class TextLine(
var isImage: Boolean = false
) {
val columns: List<TextColumn> get() = textColumns
val columns: List<BaseColumn> get() = textColumns
val charSize: Int get() = textColumns.size
val lineStart: Float get() = textColumns.firstOrNull()?.start ?: 0f
val lineEnd: Float get() = textColumns.lastOrNull()?.end ?: 0f
fun addColumn(column: TextColumn) {
fun addColumn(column: BaseColumn) {
textColumns.add(column)
}
fun getColumn(index: Int): TextColumn {
fun getColumn(index: Int): BaseColumn {
return textColumns.getOrElse(index) {
textColumns.last()
}
}
fun getColumnReverseAt(index: Int): TextColumn {
fun getColumnReverseAt(index: Int): BaseColumn {
return textColumns[textColumns.lastIndex - index]
}

@ -119,11 +119,7 @@ data class TextPage(
val cw = StaticLayout.getDesiredWidth(char, ChapterProvider.contentPaint)
val x1 = x + cw
textLine.addColumn(
TextColumn(
char,
start = x,
end = x1
)
TextColumn(start = x, end = x1, char)
)
x = x1
}

@ -13,10 +13,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.model.ReadBook
import io.legado.app.ui.book.read.page.entities.TextChapter
import io.legado.app.ui.book.read.page.entities.TextColumn
import io.legado.app.ui.book.read.page.entities.TextLine
import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.ui.book.read.page.entities.*
import io.legado.app.utils.*
import splitties.init.appCtx
import java.util.*
@ -268,7 +265,7 @@ object ChapterProvider {
Pair(0f, width.toFloat())
}
textLine.addColumn(
TextColumn(charData = src, start = x + start, end = x + end, style = 1)
ImageColumn(start = x + start, end = x + end, src = src)
)
textPages.last().addLine(textLine)
}
@ -501,20 +498,27 @@ object ChapterProvider {
ImageProvider.cacheImage(book, src, ReadBook.bookSource)
textLine.addColumn(
TextColumn(
charData = src,
start = absStartX + xStart,
end = absStartX + xEnd,
style = 1
charData = src
)
)
} else {
textLine.addColumn(
val column = if (isLineEnd && char == reviewChar) {
ReviewColumn(
start = absStartX + xStart,
end = absStartX + xEnd,
count = 1
)
} else {
TextColumn(
charData = char,
start = absStartX + xStart,
end = absStartX + xEnd,
style = if (isLineEnd && char == reviewChar) 2 else 0
charData = char
)
}
textLine.addColumn(
column
)
}
}

Loading…
Cancel
Save