mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Use OutlineSpan approach from CarlosEsco/Neko to avoid infinite redraws
Based on work by @arsonistAnt: 1876f850f6
			
			
This commit is contained in:
		@@ -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
									
								
								app/src/main/java/eu/kanade/tachiyomi/widget/OutlineSpan.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/src/main/java/eu/kanade/tachiyomi/widget/OutlineSpan.kt
									
									
									
									
									
										Normal file
									
								
							@@ -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 = this@OutlineSpan.strokeWidth
 | 
			
		||||
        }
 | 
			
		||||
        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)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user