mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 00:29:11 +01:00
Improve spoiler performance by stopping animation when backgrounded.
This commit is contained in:
@@ -10,19 +10,26 @@ import android.view.View.OnAttachStateChangeListener
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.spoiler.SpoilerAnnotation.SpoilerClickableSpan
|
||||
import org.thoughtcrime.securesms.util.getLifecycle
|
||||
|
||||
/**
|
||||
* Performs initial calculation on how to render spoilers and then delegates to actually drawing the spoiler sparkles.
|
||||
*/
|
||||
class SpoilerRendererDelegate @JvmOverloads constructor(private val view: TextView, private val renderForComposing: Boolean = false) {
|
||||
class SpoilerRendererDelegate @JvmOverloads constructor(
|
||||
private val view: TextView,
|
||||
private val renderForComposing: Boolean = false
|
||||
) {
|
||||
|
||||
private val renderer: SpoilerRenderer
|
||||
private val spoilerDrawable: SpoilerDrawable
|
||||
private var animatorRunning = false
|
||||
private var textColor: Int
|
||||
private var canAnimate = false
|
||||
|
||||
private val cachedAnnotations = HashMap<Int, Map<Annotation, SpoilerClickableSpan?>>()
|
||||
private val cachedMeasurements = HashMap<Int, SpanMeasurements>()
|
||||
@@ -50,7 +57,18 @@ class SpoilerRendererDelegate @JvmOverloads constructor(private val view: TextVi
|
||||
|
||||
view.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
|
||||
override fun onViewDetachedFromWindow(v: View) = stopAnimating()
|
||||
override fun onViewAttachedToWindow(v: View) = Unit
|
||||
override fun onViewAttachedToWindow(v: View) {
|
||||
view.getLifecycle().addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
canAnimate = true
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
canAnimate = false
|
||||
stopAnimating()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,6 +81,10 @@ class SpoilerRendererDelegate @JvmOverloads constructor(private val view: TextVi
|
||||
}
|
||||
|
||||
fun draw(canvas: Canvas, text: Spanned, layout: Layout) {
|
||||
if (!canAnimate) {
|
||||
return
|
||||
}
|
||||
|
||||
var hasSpoilersToRender = false
|
||||
val annotations: Map<Annotation, SpoilerClickableSpan?> = cachedAnnotations.getFromCache(text) { SpoilerAnnotation.getSpoilerAndClickAnnotations(text) }
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ import androidx.annotation.DrawableRes
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.doOnNextLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.findFragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
|
||||
var View.visible: Boolean
|
||||
get() {
|
||||
@@ -56,3 +59,15 @@ fun TextView.setRelativeDrawables(
|
||||
bottom
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lifecycle associated with this view. Care must be taken to ensure
|
||||
* if activity fallback occurs that the context of the view is correct.
|
||||
*/
|
||||
fun View.getLifecycle(): Lifecycle {
|
||||
return try {
|
||||
findFragment<Fragment>().viewLifecycleOwner.lifecycle
|
||||
} catch (e: IllegalStateException) {
|
||||
ViewUtil.getActivityLifecycle(this)!!
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user