mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-07 20:31:02 -05:00
Use OutlineSpan approach from CarlosEsco/Neko to avoid infinite redraws
Based on work by @arsonistAnt: 1876f850f6
This commit is contained in:
parent
f715478070
commit
745f8d32b5
2 changed files with 75 additions and 24 deletions
|
@ -2,15 +2,14 @@ package eu.kanade.tachiyomi.ui.reader
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.style.ScaleXSpan
|
import android.text.style.ScaleXSpan
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import eu.kanade.tachiyomi.widget.OutlineSpan
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page indicator found at the bottom of the reader
|
* Page indicator found at the bottom of the reader
|
||||||
|
@ -20,19 +19,8 @@ class PageIndicatorTextView(
|
||||||
attrs: AttributeSet? = null
|
attrs: AttributeSet? = null
|
||||||
) : AppCompatTextView(context, attrs) {
|
) : AppCompatTextView(context, attrs) {
|
||||||
|
|
||||||
private val fillColor = Color.rgb(235, 235, 235)
|
init {
|
||||||
private val strokeColor = Color.rgb(45, 45, 45)
|
setTextColor(fillColor)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
|
@ -42,20 +30,26 @@ class PageIndicatorTextView(
|
||||||
val currText = " $text "
|
val currText = " $text "
|
||||||
|
|
||||||
// Also add a bit of spacing between each character, as the stroke overlaps them
|
// 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) {
|
for (i in 1..lastIndex step 2) {
|
||||||
finalText.setSpan(ScaleXSpan(0.1f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
setSpan(ScaleXSpan(0.2f), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.setText(finalText, TextView.BufferType.SPANNABLE)
|
super.setText(finalText, TextView.BufferType.SPANNABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
// We need to use reflection to set the text color instead of using [setTextColor],
|
private val fillColor = Color.rgb(235, 235, 235)
|
||||||
// otherwise the view is invalidated inside [onDraw] and there's an infinite loop
|
private val strokeColor = Color.rgb(45, 45, 45)
|
||||||
val textColorField = TextView::class.java.getDeclaredField("mCurTextColor").apply {
|
|
||||||
isAccessible = true
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue