Move ReaderProgressIndicator to compose

This commit is contained in:
tarsin committed 2023-07-08 14:34:12 +08:00
1 parent 64d3849b62
commit 07b1f39796
4 files changed
+81 -82

No files matched your search

@@ -0,0 +1,56 @@
package eu.kanade.tachiyomi.ui.reader.viewer
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
@Composable
fun CombinedCircularProgressIndicator(
progress: Float,
) {
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "progress",
)
AnimatedContent(
targetState = progress == 0f,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = "progressState",
) { indeterminate ->
if (indeterminate) {
// Indeterminate
CircularProgressIndicator()
} else {
// Determinate
val infiniteTransition = rememberInfiniteTransition(label = "infiniteRotation")
val rotation by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(2000, easing = LinearEasing),
repeatMode = RepeatMode.Restart,
),
label = "rotation",
)
CircularProgressIndicator(
progress = animatedProgress,
modifier = Modifier.rotate(rotation),
)
}
}
}
@@ -2,93 +2,48 @@ package eu.kanade.tachiyomi.ui.reader.viewer
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import android.widget.FrameLayout
import androidx.annotation.IntRange
import com.google.android.material.progressindicator.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.view.isVisible
import com.google.accompanist.themeadapter.material3.Mdc3Theme
/**
* A wrapper for [CircularProgressIndicator] that always rotates.
*
* By always rotating we give the feedback to the user that the application isn't 'stuck'.
*/
class ReaderProgressIndicator @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : FrameLayout(context, attrs, defStyleAttr) {
private val indicator: CircularProgressIndicator
private val rotateAnimation by lazy {
RotateAnimation(
0F,
360F,
Animation.RELATIVE_TO_SELF,
0.5F,
Animation.RELATIVE_TO_SELF,
0.5F,
).apply {
interpolator = LinearInterpolator()
repeatCount = Animation.INFINITE
duration = 4000
}
}
) : AbstractComposeView(context, attrs, defStyleAttr) {
init {
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
indicator = CircularProgressIndicator(context)
indicator.max = 100
indicator.isIndeterminate = true
addView(indicator)
layoutParams = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity.CENTER)
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool)
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
updateRotateAnimation()
}
private var progress by mutableFloatStateOf(0f)
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
updateRotateAnimation()
@Composable
override fun Content() {
Mdc3Theme {
CombinedCircularProgressIndicator(progress = progress)
}
}
fun show() {
indicator.show()
updateRotateAnimation()
isVisible = true
}
fun hide() {
indicator.hide()
updateRotateAnimation()
isVisible = false
}
/**
* Sets the current indicator progress to the specified value.
*
* @param progress Indicator will be set indeterminate if this value is 0
*/
fun setProgress(@IntRange(from = 0, to = 100) progress: Int, animated: Boolean = true) {
if (progress > 0) {
indicator.setProgressCompat(progress, animated)
} else if (!indicator.isIndeterminate) {
indicator.hide()
indicator.isIndeterminate = true
indicator.show()
}
updateRotateAnimation()
}
private fun updateRotateAnimation() {
if (isAttachedToWindow && indicator.isShown && !indicator.isIndeterminate) {
if (animation == null) {
startAnimation(rotateAnimation)
}
} else {
clearAnimation()
}
fun setProgress(@IntRange(from = 0, to = 100) progress: Int) {
this.progress = progress / 100f
}
}
@@ -4,10 +4,8 @@ import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.view.Gravity
import android.view.LayoutInflater
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.hippo.ehviewer.databinding.ReaderErrorBinding
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
@@ -39,11 +37,7 @@ class PagerPageHolder(
/**
* Loading progress bar to indicate the current progress.
*/
private val progressIndicator: ReaderProgressIndicator = ReaderProgressIndicator(readerThemedContext).apply {
updateLayoutParams<LayoutParams> {
gravity = Gravity.CENTER
}
}
private val progressIndicator: ReaderProgressIndicator = ReaderProgressIndicator(readerThemedContext)
/**
* Error layout to show when the image fails to load.
@@ -2,14 +2,12 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.view.Gravity
import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.hippo.ehviewer.databinding.ReaderErrorBinding
import eu.kanade.tachiyomi.source.model.Page
@@ -116,7 +114,7 @@ class WebtoonPageHolder(
removeErrorLayout()
frame.recycle()
progressIndicator.setProgress(0, animated = false)
progressIndicator.setProgress(0)
}
/**
@@ -238,11 +236,7 @@ class WebtoonPageHolder(
progressContainer = FrameLayout(context)
frame.addView(progressContainer, MATCH_PARENT, defaultHeight)
val progress = ReaderProgressIndicator(context).apply {
updateLayoutParams<FrameLayout.LayoutParams> {
gravity = Gravity.CENTER
}
}
val progress = ReaderProgressIndicator(context)
progressContainer.addView(progress)
return progress
}