From 07b1f397963a0f4283d9aa7f2edcb68a7dcd3b15 Mon Sep 17 00:00:00 2001 From: tarsin Date: Sat, 8 Jul 2023 14:34:12 +0800 Subject: [PATCH] Move ReaderProgressIndicator to compose --- .../viewer/CircularProgressIndicator.kt | 56 ++++++++++++ .../reader/viewer/ReaderProgressIndicator.kt | 89 +++++-------------- .../ui/reader/viewer/pager/PagerPageHolder.kt | 8 +- .../viewer/webtoon/WebtoonPageHolder.kt | 10 +-- 4 files changed, 81 insertions(+), 82 deletions(-) create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/CircularProgressIndicator.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/CircularProgressIndicator.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/CircularProgressIndicator.kt new file mode 100644 index 000000000..1828af27d --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/CircularProgressIndicator.kt @@ -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), + ) + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressIndicator.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressIndicator.kt index 75f710686..0e5410342 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressIndicator.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressIndicator.kt @@ -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 } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 4300cbf22..786aa48f6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -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 { - gravity = Gravity.CENTER - } - } + private val progressIndicator: ReaderProgressIndicator = ReaderProgressIndicator(readerThemedContext) /** * Error layout to show when the image fails to load. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt index 13710049e..1ab973947 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt @@ -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 { - gravity = Gravity.CENTER - } - } + val progress = ReaderProgressIndicator(context) progressContainer.addView(progress) return progress }