Move ReaderProgressIndicator to compose
This commit is contained in:
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
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user