From 1111e36c412e6cb9d4c22baa3ea1214abece3705 Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Thu, 8 Feb 2024 23:01:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/help/config/ReadBookConfig.kt | 25 +++-- .../java/io/legado/app/model/CacheBook.kt | 2 - .../app/ui/book/read/page/ContentTextView.kt | 32 +++++- .../legado/app/ui/book/read/page/ReadView.kt | 7 +- .../read/page/delegate/CoverPageDelegate.kt | 98 ++++++++++++++----- .../book/read/page/delegate/PageDelegate.kt | 1 + .../read/page/delegate/SlidePageDelegate.kt | 72 ++++++++++++-- .../io/legado/app/utils/ViewExtensions.kt | 13 +++ 8 files changed, 207 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt index a43f4ca34..a390ead0f 100644 --- a/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt @@ -537,20 +537,33 @@ object ReadBookConfig { var footerMode: Int = 0 ) { + private var textColorIntEInk = Color.parseColor(textColorEInk) + private var textColorIntNight = Color.parseColor(textColorNight) + private var textColorInt = Color.parseColor(textColor) + fun setCurTextColor(color: Int) { when { - AppConfig.isEInkMode -> textColorEInk = "#${color.hexString}" - AppConfig.isNightTheme -> textColorNight = "#${color.hexString}" - else -> textColor = "#${color.hexString}" + AppConfig.isEInkMode -> { + textColorEInk = "#${color.hexString}" + textColorIntEInk = color + } + AppConfig.isNightTheme -> { + textColorNight = "#${color.hexString}" + textColorIntNight = color + } + else -> { + textColor = "#${color.hexString}" + textColorInt = color + } } ChapterProvider.upStyle() } fun curTextColor(): Int { return when { - AppConfig.isEInkMode -> Color.parseColor(textColorEInk) - AppConfig.isNightTheme -> Color.parseColor(textColorNight) - else -> Color.parseColor(textColor) + AppConfig.isEInkMode -> textColorIntEInk + AppConfig.isNightTheme -> textColorIntNight + else -> textColorInt } } diff --git a/app/src/main/java/io/legado/app/model/CacheBook.kt b/app/src/main/java/io/legado/app/model/CacheBook.kt index aee3ce044..41c5847a1 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -15,13 +15,11 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.webBook.WebBook import io.legado.app.service.CacheBookService import io.legado.app.utils.postEvent - import io.legado.app.utils.startService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.delay - import java.util.concurrent.ConcurrentHashMap import kotlin.coroutines.CoroutineContext 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 874b66024..11fb9d542 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 @@ -3,11 +3,15 @@ package io.legado.app.ui.book.read.page import android.content.Context import android.graphics.Canvas import android.graphics.Paint +import android.graphics.Picture import android.graphics.RectF +import android.os.Build import android.util.AttributeSet import android.view.MotionEvent import android.view.View +import androidx.core.graphics.record import io.legado.app.R +import io.legado.app.constant.PageAnim import io.legado.app.constant.PreferKey import io.legado.app.data.entities.Bookmark import io.legado.app.help.book.isImage @@ -61,6 +65,10 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at //滚动参数 private val pageFactory: TextPageFactory get() = callBack.pageFactory private var pageOffset = 0 + private lateinit var picture: Picture + private var pictureIsDirty = true + private val atLeastApi23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + private val isNoAnim get() = ReadBook.pageAnim() == PageAnim.noAnim //绘制图片的paint private val imagePaint by lazy { @@ -71,6 +79,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at init { callBack = activity as CallBack + if (atLeastApi23) { + picture = Picture() + } } /** @@ -108,7 +119,17 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at canvas.translate(0f, scrollY.toFloat()) } canvas.clipRect(visibleRect) - drawPage(canvas) + if (atLeastApi23 && !callBack.isScroll && !isNoAnim) { + if (pictureIsDirty) { + pictureIsDirty = false + picture.record(width, height) { + drawPage(this) + } + } + canvas.drawPicture(picture) + } else { + drawPage(canvas) + } } /** @@ -288,6 +309,15 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at invalidate() } + override fun invalidate() { + super.invalidate() + invalidatePicture() + } + + private fun invalidatePicture() { + pictureIsDirty = true + } + /** * 重置滚动位置 */ 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 1e4e24bbb..70833c053 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 @@ -104,7 +104,6 @@ class ReadView(context: Context, attrs: AttributeSet) : addView(nextPage) addView(curPage) addView(prevPage) - nextPage.invisible() prevPage.invisible() curPage.markAsMainView() if (!isInEditMode) { @@ -516,6 +515,12 @@ class ReadView(context: Context, attrs: AttributeSet) : } } (pageDelegate as? ScrollPageDelegate)?.noAnim = AppConfig.noAnimScrollPage + pageDelegate?.setViewSize(width, height) + if (pageDelegate is NoAnimPageDelegate) { + nextPage.invisible() + } else { + nextPage.visible() + } } /** diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/CoverPageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/CoverPageDelegate.kt index 1b92f160c..f9fb0695c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/CoverPageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/CoverPageDelegate.kt @@ -2,7 +2,11 @@ package io.legado.app.ui.book.read.page.delegate import android.graphics.Canvas import android.graphics.Matrix +import android.graphics.Picture import android.graphics.drawable.GradientDrawable +import android.os.Build +import androidx.core.graphics.withClip +import androidx.core.graphics.withTranslation import io.legado.app.ui.book.read.page.ReadView import io.legado.app.ui.book.read.page.entities.PageDirection import io.legado.app.utils.screenshot @@ -11,12 +15,23 @@ class CoverPageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { private val bitmapMatrix = Matrix() private val shadowDrawableR: GradientDrawable + private lateinit var curPicture: Picture + private lateinit var prevPicture: Picture + private lateinit var nextPicture: Picture + + private val atLeastApi23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + init { val shadowColors = intArrayOf(0x66111111, 0x00000000) shadowDrawableR = GradientDrawable( GradientDrawable.Orientation.LEFT_RIGHT, shadowColors ) shadowDrawableR.gradientType = GradientDrawable.LINEAR_GRADIENT + if (atLeastApi23) { + curPicture = Picture() + prevPicture = Picture() + nextPicture = Picture() + } } override fun onDraw(canvas: Canvas) { @@ -32,52 +47,84 @@ class CoverPageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { val distanceX = if (offsetX > 0) offsetX - viewWidth else offsetX + viewWidth if (mDirection == PageDirection.PREV) { if (offsetX <= viewWidth) { - bitmapMatrix.setTranslate(distanceX, 0.toFloat()) - prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } - addShadow(distanceX.toInt(), canvas) + if (!atLeastApi23) { + bitmapMatrix.setTranslate(distanceX, 0.toFloat()) + prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + } else { + canvas.withTranslation(distanceX) { + drawPicture(prevPicture) + } + } + addShadow(distanceX, canvas) } else { - prevBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) } - } - } else if (mDirection == PageDirection.NEXT) { - bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat()) - nextBitmap?.let { - canvas.apply { - save() - val width = it.width.toFloat() - val height = it.height.toFloat() - clipRect(width + offsetX, 0f, width, height) - drawBitmap(it, 0f, 0f, null) - restore() + if (!atLeastApi23) { + prevBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) } + } else { + canvas.drawPicture(prevPicture) } } - curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } - addShadow(distanceX.toInt(), canvas) + } else if (mDirection == PageDirection.NEXT) { + if (!atLeastApi23) { + bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat()) + nextBitmap?.let { + val width = it.width.toFloat() + val height = it.height.toFloat() + canvas.withClip(width + offsetX, 0f, width, height) { + drawBitmap(it, 0f, 0f, null) + } + } + curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + } else { + val width = nextPicture.width.toFloat() + val height = nextPicture.height.toFloat() + canvas.withClip(width + offsetX, 0f, width, height) { + drawPicture(nextPicture) + } + canvas.withTranslation(distanceX - viewWidth) { + drawPicture(curPicture) + } + } + addShadow(distanceX, canvas) } } override fun setBitmap() { when (mDirection) { - PageDirection.PREV -> { + PageDirection.PREV -> if (!atLeastApi23) { prevBitmap = prevPage.screenshot(prevBitmap, canvas) + } else { + prevPage.screenshot(prevPicture) } - PageDirection.NEXT -> { + + PageDirection.NEXT -> if (!atLeastApi23) { nextBitmap = nextPage.screenshot(nextBitmap, canvas) curBitmap = curPage.screenshot(curBitmap, canvas) + } else { + nextPage.screenshot(nextPicture) + curPage.screenshot(curPicture) } + else -> Unit } } - private fun addShadow(left: Int, canvas: Canvas) { - if (left < 0) { - shadowDrawableR.setBounds(left + viewWidth, 0, left + viewWidth + 30, viewHeight) - shadowDrawableR.draw(canvas) - } else if (left > 0) { - shadowDrawableR.setBounds(left, 0, left + 30, viewHeight) + private fun addShadow(left: Float, canvas: Canvas) { + if (left == 0f) return + val dx = if (left < 0) { + left + viewWidth + } else { + left + } + canvas.withTranslation(dx) { shadowDrawableR.draw(canvas) } } + override fun setViewSize(width: Int, height: Int) { + super.setViewSize(width, height) + shadowDrawableR.setBounds(0, 0, 30, viewHeight) + } + override fun onAnimStop() { if (!isCancel) { readView.fillPage(mDirection) @@ -97,6 +144,7 @@ class CoverPageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { } else { -(touchX + (viewWidth - startX)) } + else -> distanceX = if (isCancel) { -(touchX - startX) diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt index 4a3beb3bf..7be18c761 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt @@ -90,6 +90,7 @@ abstract class PageDelegate(protected val readView: ReadView) { } } + @CallSuper open fun setViewSize(width: Int, height: Int) { viewWidth = width viewHeight = height diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/SlidePageDelegate.kt b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/SlidePageDelegate.kt index 417ea746a..103cf3a09 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/delegate/SlidePageDelegate.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/delegate/SlidePageDelegate.kt @@ -2,13 +2,50 @@ package io.legado.app.ui.book.read.page.delegate import android.graphics.Canvas import android.graphics.Matrix +import android.graphics.Picture +import android.os.Build +import androidx.core.graphics.withTranslation import io.legado.app.ui.book.read.page.ReadView import io.legado.app.ui.book.read.page.entities.PageDirection +import io.legado.app.utils.screenshot class SlidePageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { private val bitmapMatrix = Matrix() + private lateinit var curPicture: Picture + private lateinit var prevPicture: Picture + private lateinit var nextPicture: Picture + + private val atLeastApi23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + + init { + if (atLeastApi23) { + curPicture = Picture() + prevPicture = Picture() + nextPicture = Picture() + } + } + + override fun setBitmap() { + if (!atLeastApi23) { + return super.setBitmap() + } + when (mDirection) { + PageDirection.PREV -> { + prevPage.screenshot(prevPicture) + curPage.screenshot(curPicture) + } + + PageDirection.NEXT -> { + nextPage.screenshot(nextPicture) + curPage.screenshot(curPicture) + } + + else -> Unit + } + } + override fun onAnimStart(animationSpeed: Int) { val distanceX: Float when (mDirection) { @@ -22,6 +59,7 @@ class SlidePageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { } else { -(touchX + (viewWidth - startX)) } + else -> distanceX = if (isCancel) { -(touchX - startX) @@ -41,15 +79,33 @@ class SlidePageDelegate(readView: ReadView) : HorizontalPageDelegate(readView) { val distanceX = if (offsetX > 0) offsetX - viewWidth else offsetX + viewWidth if (!isRunning) return if (mDirection == PageDirection.PREV) { - bitmapMatrix.setTranslate(distanceX + viewWidth, 0.toFloat()) - curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } - bitmapMatrix.setTranslate(distanceX, 0.toFloat()) - prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + if (!atLeastApi23) { + bitmapMatrix.setTranslate(distanceX + viewWidth, 0.toFloat()) + curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + bitmapMatrix.setTranslate(distanceX, 0.toFloat()) + prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + } else { + canvas.withTranslation(distanceX + viewWidth) { + drawPicture(curPicture) + } + canvas.withTranslation(distanceX) { + drawPicture(prevPicture) + } + } } else if (mDirection == PageDirection.NEXT) { - bitmapMatrix.setTranslate(distanceX, 0.toFloat()) - nextBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } - bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat()) - curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + if (!atLeastApi23) { + bitmapMatrix.setTranslate(distanceX, 0.toFloat()) + nextBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat()) + curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) } + } else { + canvas.withTranslation(distanceX) { + drawPicture(nextPicture) + } + canvas.withTranslation(distanceX - viewWidth) { + drawPicture(curPicture) + } + } } } diff --git a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt index 91fb16c9f..03096add4 100644 --- a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt @@ -7,6 +7,7 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color +import android.graphics.Picture import android.os.Build import android.text.Html import android.view.MotionEvent @@ -25,6 +26,8 @@ import androidx.annotation.ColorInt import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.menu.MenuPopupHelper import androidx.appcompat.widget.PopupMenu +import androidx.core.graphics.record +import androidx.core.graphics.withTranslation import androidx.core.view.get import androidx.recyclerview.widget.RecyclerView import androidx.viewpager.widget.ViewPager @@ -163,6 +166,16 @@ fun View.screenshot(bitmap: Bitmap? = null, canvas: Canvas? = null): Bitmap? { } } +fun View.screenshot(picture: Picture) { + if (width > 0 && height > 0) { + picture.record(width, height) { + withTranslation(-scrollX.toFloat(), -scrollY.toFloat()) { + draw(this) + } + } + } +} + fun View.setPaddingBottom(bottom: Int) { setPadding(paddingLeft, paddingTop, paddingRight, bottom) }