Bladeren bron

Use OutlineSpan approach from CarlosEsco/Neko to avoid infinite redraws

Based on work by @arsonistAnt: https://github.com/CarlosEsco/Neko/commit/1876f850f6177b756ef623c9baedd65241a424d5
arkon 5 jaren geleden
bovenliggende
commit
745f8d32b5

+ 18 - 24
app/src/main/java/eu/kanade/tachiyomi/ui/reader/PageIndicatorTextView.kt

@@ -2,15 +2,14 @@ package eu.kanade.tachiyomi.ui.reader
 
 import android.annotation.SuppressLint
 import android.content.Context
-import android.graphics.Canvas
 import android.graphics.Color
-import android.graphics.Paint
-import androidx.appcompat.widget.AppCompatTextView
 import android.text.Spannable
 import android.text.SpannableString
 import android.text.style.ScaleXSpan
 import android.util.AttributeSet
 import android.widget.TextView
+import androidx.appcompat.widget.AppCompatTextView
+import eu.kanade.tachiyomi.widget.OutlineSpan
 
 /**
  * Page indicator found at the bottom of the reader
@@ -20,19 +19,8 @@ class PageIndicatorTextView(
         attrs: AttributeSet? = null
 ) : AppCompatTextView(context, attrs) {
 
-    private val fillColor = Color.rgb(235, 235, 235)
-    private val strokeColor = Color.rgb(45, 45, 45)
-
-    override fun onDraw(canvas: Canvas) {
-        textColorField.set(this, strokeColor)
-        paint.strokeWidth = 4f
-        paint.style = Paint.Style.STROKE
-        super.onDraw(canvas)
-
-        textColorField.set(this, fillColor)
-        paint.strokeWidth = 0f
-        paint.style = Paint.Style.FILL
-        super.onDraw(canvas)
+    init {
+        setTextColor(fillColor)
     }
 
     @SuppressLint("SetTextI18n")
@@ -42,20 +30,26 @@ class PageIndicatorTextView(
         val currText = " $text "
 
         // Also add a bit of spacing between each character, as the stroke overlaps them
-        val finalText = SpannableString(currText.asIterable().joinToString("\u00A0"))
+        val finalText = SpannableString(currText.asIterable().joinToString("\u00A0")).apply {
+            // Apply text outline
+            setSpan(spanOutline, 1, length-1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
 
-        for (i in 1..finalText.lastIndex step 2) {
-            finalText.setSpan(ScaleXSpan(0.1f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+            for (i in 1..lastIndex step 2) {
+                setSpan(ScaleXSpan(0.2f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+            }
         }
 
         super.setText(finalText, TextView.BufferType.SPANNABLE)
     }
 
     private companion object {
-        // We need to use reflection to set the text color instead of using [setTextColor],
-        // otherwise the view is invalidated inside [onDraw] and there's an infinite loop
-        val textColorField = TextView::class.java.getDeclaredField("mCurTextColor").apply {
-            isAccessible = true
-        }!!
+        private val fillColor = Color.rgb(235, 235, 235)
+        private val strokeColor = Color.rgb(45, 45, 45)
+
+        // A span object with text outlining properties
+        val spanOutline = OutlineSpan(
+                strokeColor = strokeColor,
+                strokeWidth = 4f
+        )
     }
 }

+ 57 - 0
app/src/main/java/eu/kanade/tachiyomi/widget/OutlineSpan.kt

@@ -0,0 +1,57 @@
+package eu.kanade.tachiyomi.widget
+
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.text.style.ReplacementSpan
+import androidx.annotation.ColorInt
+import androidx.annotation.Dimension
+
+/**
+ * Source: https://github.com/santaevpavel
+ *
+ * A class that draws the outlines of a text when given a stroke color and stroke width.
+ */
+class OutlineSpan(
+        @ColorInt private val strokeColor: Int,
+        @Dimension private val strokeWidth: Float
+) : ReplacementSpan() {
+
+    override fun getSize(
+            paint: Paint,
+            text: CharSequence,
+            start: Int,
+            end: Int,
+            fm: Paint.FontMetricsInt?
+    ): Int {
+        return paint.measureText(text.toString().substring(start until end)).toInt()
+    }
+
+    override fun draw(
+            canvas: Canvas,
+            text: CharSequence,
+            start: Int,
+            end: Int,
+            x: Float,
+            top: Int,
+            y: Int,
+            bottom: Int,
+            paint: Paint
+    ) {
+        val originTextColor = paint.color
+
+        paint.apply {
+            color = strokeColor
+            style = Paint.Style.STROKE
+            this.strokeWidth = [email protected]
+        }
+        canvas.drawText(text, start, end, x, y.toFloat(), paint)
+
+        paint.apply {
+            color = originTextColor
+            style = Paint.Style.FILL
+        }
+
+        canvas.drawText(text, start, end, x, y.toFloat(), paint)
+    }
+
+}