Horis 2 yıl önce
ebeveyn
işleme
72ad6209db

+ 19 - 6
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
             }
         }
 

+ 0 - 2
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
 

+ 31 - 1
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
+    }
+
     /**
      * 重置滚动位置
      */

+ 6 - 1
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()
+        }
     }
 
     /**

+ 69 - 21
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) }
+                if (!atLeastApi23) {
+                    prevBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
+                } else {
+                    canvas.drawPicture(prevPicture)
+                }
             }
         } else if (mDirection == PageDirection.NEXT) {
-            bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat())
-            nextBitmap?.let {
-                canvas.apply {
-                    save()
+            if (!atLeastApi23) {
+                bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat())
+                nextBitmap?.let {
                     val width = it.width.toFloat()
                     val height = it.height.toFloat()
-                    clipRect(width + offsetX, 0f, width, height)
-                    drawBitmap(it, 0f, 0f, null)
-                    restore()
+                    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)
                 }
             }
-            curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
-            addShadow(distanceX.toInt(), canvas)
+            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)

+ 1 - 0
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

+ 64 - 8
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)
+                }
+            }
         }
     }
 

+ 13 - 0
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)
 }