Reader loading progress indicator changes (#5587)
* Use CircularProgressIndicator on PageHolder Manually rotate the CircularProgressIndicator inside a wrapper view instead of drawing our own custom indicator. * Use CircularProgressIndicator on TransitionHolder
This commit is contained in:
parent
8bd965267c
commit
6ba779fb7a
@ -1,215 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.ui.reader.viewer
|
|
||||||
|
|
||||||
import android.animation.ObjectAnimator
|
|
||||||
import android.animation.ValueAnimator
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.graphics.RectF
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.DecelerateInterpolator
|
|
||||||
import android.view.animation.LinearInterpolator
|
|
||||||
import android.view.animation.RotateAnimation
|
|
||||||
import androidx.core.animation.doOnCancel
|
|
||||||
import androidx.core.animation.doOnEnd
|
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A custom progress bar that always rotates while being determinate. By always rotating we give
|
|
||||||
* the feedback to the user that the application isn't 'stuck', and by making it determinate the
|
|
||||||
* user also approximately knows how much the operation will take.
|
|
||||||
*/
|
|
||||||
class ReaderProgressBar @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0
|
|
||||||
) : View(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current sweep angle. It always starts at 10% because otherwise the bar and the rotation
|
|
||||||
* wouldn't be visible.
|
|
||||||
*/
|
|
||||||
private var sweepAngle = 10f
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the parent views are also visible.
|
|
||||||
*/
|
|
||||||
private var aggregatedIsVisible = false
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The paint to use to draw the progress bar.
|
|
||||||
*/
|
|
||||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
||||||
color = context.getResourceColor(R.attr.colorAccent)
|
|
||||||
isAntiAlias = true
|
|
||||||
strokeCap = Paint.Cap.ROUND
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The rectangle of the canvas where the progress bar should be drawn. This is calculated on
|
|
||||||
* layout.
|
|
||||||
*/
|
|
||||||
private val ovalRect = RectF()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The rotation animation to use while the progress bar is visible.
|
|
||||||
*/
|
|
||||||
private val rotationAnimation 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the view is layout. The position and thickness of the progress bar is calculated.
|
|
||||||
*/
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
|
||||||
|
|
||||||
val diameter = min(width, height)
|
|
||||||
val thickness = diameter / 10f
|
|
||||||
val pad = thickness / 2f
|
|
||||||
ovalRect.set(pad, pad, diameter - pad, diameter - pad)
|
|
||||||
|
|
||||||
paint.strokeWidth = thickness
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the view is being drawn. An arc is drawn with the calculated rectangle. The
|
|
||||||
* animation will take care of rotation.
|
|
||||||
*/
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
super.onDraw(canvas)
|
|
||||||
canvas.drawArc(ovalRect, -90f, sweepAngle, false, paint)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the sweep angle to use from the progress.
|
|
||||||
*/
|
|
||||||
private fun calcSweepAngleFromProgress(progress: Int): Float {
|
|
||||||
return 360f / 100 * progress
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when this view is attached to window. It starts the rotation animation.
|
|
||||||
*/
|
|
||||||
override fun onAttachedToWindow() {
|
|
||||||
super.onAttachedToWindow()
|
|
||||||
startAnimation()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when this view is detached to window. It stops the rotation animation.
|
|
||||||
*/
|
|
||||||
override fun onDetachedFromWindow() {
|
|
||||||
stopAnimation()
|
|
||||||
super.onDetachedFromWindow()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the visibility of this view changes.
|
|
||||||
*/
|
|
||||||
override fun setVisibility(visibility: Int) {
|
|
||||||
super.setVisibility(visibility)
|
|
||||||
val isVisible = visibility == VISIBLE
|
|
||||||
if (isVisible) {
|
|
||||||
startAnimation()
|
|
||||||
} else {
|
|
||||||
stopAnimation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the rotation animation if needed.
|
|
||||||
*/
|
|
||||||
private fun startAnimation() {
|
|
||||||
if (visibility != VISIBLE || windowVisibility != VISIBLE || animation != null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
animation = rotationAnimation
|
|
||||||
animation.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the rotation animation if needed.
|
|
||||||
*/
|
|
||||||
private fun stopAnimation() {
|
|
||||||
clearAnimation()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides this progress bar with an optional fade out if [animate] is true.
|
|
||||||
*/
|
|
||||||
fun hide(animate: Boolean = false) {
|
|
||||||
if (isGone) return
|
|
||||||
|
|
||||||
if (!animate) {
|
|
||||||
isVisible = false
|
|
||||||
} else {
|
|
||||||
ObjectAnimator.ofFloat(this, "alpha", 1f, 0f).apply {
|
|
||||||
interpolator = DecelerateInterpolator()
|
|
||||||
duration = 1000
|
|
||||||
doOnEnd {
|
|
||||||
isVisible = false
|
|
||||||
alpha = 1f
|
|
||||||
}
|
|
||||||
doOnCancel {
|
|
||||||
alpha = 1f
|
|
||||||
}
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Completes this progress bar and fades out the view.
|
|
||||||
*/
|
|
||||||
fun completeAndFadeOut() {
|
|
||||||
setRealProgress(100)
|
|
||||||
hide(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set progress of the circular progress bar ensuring a min max range in order to notice the
|
|
||||||
* rotation animation.
|
|
||||||
*/
|
|
||||||
fun setProgress(progress: Int) {
|
|
||||||
// Scale progress in [10, 95] range
|
|
||||||
val scaledProgress = 85 * progress / 100 + 10
|
|
||||||
setRealProgress(scaledProgress)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the real progress of the circular progress bar. Note that if this progres is 0 or
|
|
||||||
* 100, the rotation animation won't be noticed by the user because nothing changes in the
|
|
||||||
* canvas.
|
|
||||||
*/
|
|
||||||
private fun setRealProgress(progress: Int) {
|
|
||||||
ValueAnimator.ofFloat(sweepAngle, calcSweepAngleFromProgress(progress)).apply {
|
|
||||||
interpolator = DecelerateInterpolator()
|
|
||||||
duration = 250
|
|
||||||
addUpdateListener { valueAnimator ->
|
|
||||||
sweepAngle = valueAnimator.animatedValue as Float
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,77 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.reader.viewer
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
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 androidx.core.view.isVisible
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for [CircularProgressIndicator] that always rotates while being determinate.
|
||||||
|
*
|
||||||
|
* By always rotating we give the feedback to the user that the application isn't 'stuck',
|
||||||
|
* and by making it determinate the user also approximately knows how much the operation will take.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
|
||||||
|
indicator = CircularProgressIndicator(context)
|
||||||
|
indicator.max = 100
|
||||||
|
addView(indicator)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow()
|
||||||
|
if (indicator.isVisible && animation == null) {
|
||||||
|
startAnimation(rotateAnimation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow()
|
||||||
|
clearAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun show() {
|
||||||
|
indicator.show()
|
||||||
|
if (animation == null) {
|
||||||
|
startAnimation(rotateAnimation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hide() {
|
||||||
|
indicator.hide()
|
||||||
|
clearAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setProgress(@IntRange(from = 0, to = 100) progress: Int, animated: Boolean = true) {
|
||||||
|
indicator.setProgressCompat(progress, animated)
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import android.widget.ImageView
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
import coil.request.CachePolicy
|
import coil.request.CachePolicy
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
@ -24,7 +25,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.InsertPage
|
import eu.kanade.tachiyomi.ui.reader.model.InsertPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig.ZoomType
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
@ -56,7 +57,11 @@ class PagerPageHolder(
|
|||||||
/**
|
/**
|
||||||
* Loading progress bar to indicate the current progress.
|
* Loading progress bar to indicate the current progress.
|
||||||
*/
|
*/
|
||||||
private val progressBar = createProgressBar()
|
private val progressIndicator = ReaderProgressIndicator(context).apply {
|
||||||
|
updateLayoutParams<LayoutParams> {
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image view that supports subsampling on zoom.
|
* Image view that supports subsampling on zoom.
|
||||||
@ -95,7 +100,7 @@ class PagerPageHolder(
|
|||||||
private var readImageHeaderSubscription: Subscription? = null
|
private var readImageHeaderSubscription: Subscription? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addView(progressBar)
|
addView(progressIndicator)
|
||||||
observeStatus()
|
observeStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +141,7 @@ class PagerPageHolder(
|
|||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onBackpressureLatest()
|
.onBackpressureLatest()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { value -> progressBar.setProgress(value) }
|
.subscribe { value -> progressIndicator.setProgress(value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,7 +196,7 @@ class PagerPageHolder(
|
|||||||
* Called when the page is queued.
|
* Called when the page is queued.
|
||||||
*/
|
*/
|
||||||
private fun setQueued() {
|
private fun setQueued() {
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryButton?.isVisible = false
|
retryButton?.isVisible = false
|
||||||
decodeErrorLayout?.isVisible = false
|
decodeErrorLayout?.isVisible = false
|
||||||
}
|
}
|
||||||
@ -200,7 +205,7 @@ class PagerPageHolder(
|
|||||||
* Called when the page is loading.
|
* Called when the page is loading.
|
||||||
*/
|
*/
|
||||||
private fun setLoading() {
|
private fun setLoading() {
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryButton?.isVisible = false
|
retryButton?.isVisible = false
|
||||||
decodeErrorLayout?.isVisible = false
|
decodeErrorLayout?.isVisible = false
|
||||||
}
|
}
|
||||||
@ -209,7 +214,7 @@ class PagerPageHolder(
|
|||||||
* Called when the page is downloading.
|
* Called when the page is downloading.
|
||||||
*/
|
*/
|
||||||
private fun setDownloading() {
|
private fun setDownloading() {
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryButton?.isVisible = false
|
retryButton?.isVisible = false
|
||||||
decodeErrorLayout?.isVisible = false
|
decodeErrorLayout?.isVisible = false
|
||||||
}
|
}
|
||||||
@ -218,8 +223,8 @@ class PagerPageHolder(
|
|||||||
* Called when the page is ready.
|
* Called when the page is ready.
|
||||||
*/
|
*/
|
||||||
private fun setImage() {
|
private fun setImage() {
|
||||||
progressBar.isVisible = true
|
progressIndicator.setProgress(100)
|
||||||
progressBar.completeAndFadeOut()
|
progressIndicator.hide()
|
||||||
retryButton?.isVisible = false
|
retryButton?.isVisible = false
|
||||||
decodeErrorLayout?.isVisible = false
|
decodeErrorLayout?.isVisible = false
|
||||||
|
|
||||||
@ -301,7 +306,7 @@ class PagerPageHolder(
|
|||||||
* Called when the page has an error.
|
* Called when the page has an error.
|
||||||
*/
|
*/
|
||||||
private fun setError() {
|
private fun setError() {
|
||||||
progressBar.isVisible = false
|
progressIndicator.hide()
|
||||||
initRetryButton().isVisible = true
|
initRetryButton().isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,30 +314,17 @@ class PagerPageHolder(
|
|||||||
* Called when the image is decoded and going to be displayed.
|
* Called when the image is decoded and going to be displayed.
|
||||||
*/
|
*/
|
||||||
private fun onImageDecoded() {
|
private fun onImageDecoded() {
|
||||||
progressBar.isVisible = false
|
progressIndicator.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an image fails to decode.
|
* Called when an image fails to decode.
|
||||||
*/
|
*/
|
||||||
private fun onImageDecodeError() {
|
private fun onImageDecodeError() {
|
||||||
progressBar.isVisible = false
|
progressIndicator.hide()
|
||||||
initDecodeErrorLayout().isVisible = true
|
initDecodeErrorLayout().isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new progress bar.
|
|
||||||
*/
|
|
||||||
@SuppressLint("PrivateResource")
|
|
||||||
private fun createProgressBar(): ReaderProgressBar {
|
|
||||||
return ReaderProgressBar(context, null).apply {
|
|
||||||
val size = 48.dpToPx
|
|
||||||
layoutParams = LayoutParams(size, size).apply {
|
|
||||||
gravity = Gravity.CENTER
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a subsampling scale view.
|
* Initializes a subsampling scale view.
|
||||||
*/
|
*/
|
||||||
|
@ -7,8 +7,8 @@ import android.view.ViewGroup
|
|||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
@ -96,7 +96,8 @@ class PagerTransitionHolder(
|
|||||||
* Sets the loading state on the pages container.
|
* Sets the loading state on the pages container.
|
||||||
*/
|
*/
|
||||||
private fun setLoading() {
|
private fun setLoading() {
|
||||||
val progress = ProgressBar(context, null, android.R.attr.progressBarStyle)
|
val progress = CircularProgressIndicator(context)
|
||||||
|
progress.isIndeterminate = true
|
||||||
|
|
||||||
val textView = AppCompatTextView(context).apply {
|
val textView = AppCompatTextView(context).apply {
|
||||||
wrapContent()
|
wrapContent()
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
|
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
@ -14,6 +13,8 @@ import android.widget.TextView
|
|||||||
import androidx.appcompat.widget.AppCompatButton
|
import androidx.appcompat.widget.AppCompatButton
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.core.view.updateMargins
|
||||||
import coil.clear
|
import coil.clear
|
||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
import coil.request.CachePolicy
|
import coil.request.CachePolicy
|
||||||
@ -23,7 +24,7 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
@ -50,7 +51,7 @@ class WebtoonPageHolder(
|
|||||||
/**
|
/**
|
||||||
* Loading progress bar to indicate the current progress.
|
* Loading progress bar to indicate the current progress.
|
||||||
*/
|
*/
|
||||||
private val progressBar = createProgressBar()
|
private val progressIndicator = createProgressIndicator()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Progress bar container. Needed to keep a minimum height size of the holder, otherwise the
|
* Progress bar container. Needed to keep a minimum height size of the holder, otherwise the
|
||||||
@ -144,7 +145,7 @@ class WebtoonPageHolder(
|
|||||||
subsamplingImageView?.isVisible = false
|
subsamplingImageView?.isVisible = false
|
||||||
imageView?.clear()
|
imageView?.clear()
|
||||||
imageView?.isVisible = false
|
imageView?.isVisible = false
|
||||||
progressBar.setProgress(0)
|
progressIndicator.setProgress(0, animated = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,7 +178,7 @@ class WebtoonPageHolder(
|
|||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onBackpressureLatest()
|
.onBackpressureLatest()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { value -> progressBar.setProgress(value) }
|
.subscribe { value -> progressIndicator.setProgress(value) }
|
||||||
|
|
||||||
addSubscription(progressSubscription)
|
addSubscription(progressSubscription)
|
||||||
}
|
}
|
||||||
@ -235,7 +236,7 @@ class WebtoonPageHolder(
|
|||||||
*/
|
*/
|
||||||
private fun setQueued() {
|
private fun setQueued() {
|
||||||
progressContainer.isVisible = true
|
progressContainer.isVisible = true
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryContainer?.isVisible = false
|
retryContainer?.isVisible = false
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
}
|
}
|
||||||
@ -245,7 +246,7 @@ class WebtoonPageHolder(
|
|||||||
*/
|
*/
|
||||||
private fun setLoading() {
|
private fun setLoading() {
|
||||||
progressContainer.isVisible = true
|
progressContainer.isVisible = true
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryContainer?.isVisible = false
|
retryContainer?.isVisible = false
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
}
|
}
|
||||||
@ -255,7 +256,7 @@ class WebtoonPageHolder(
|
|||||||
*/
|
*/
|
||||||
private fun setDownloading() {
|
private fun setDownloading() {
|
||||||
progressContainer.isVisible = true
|
progressContainer.isVisible = true
|
||||||
progressBar.isVisible = true
|
progressIndicator.show()
|
||||||
retryContainer?.isVisible = false
|
retryContainer?.isVisible = false
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
}
|
}
|
||||||
@ -265,8 +266,8 @@ class WebtoonPageHolder(
|
|||||||
*/
|
*/
|
||||||
private fun setImage() {
|
private fun setImage() {
|
||||||
progressContainer.isVisible = true
|
progressContainer.isVisible = true
|
||||||
progressBar.isVisible = true
|
progressIndicator.setProgress(100)
|
||||||
progressBar.completeAndFadeOut()
|
progressIndicator.hide()
|
||||||
retryContainer?.isVisible = false
|
retryContainer?.isVisible = false
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
|
|
||||||
@ -342,16 +343,14 @@ class WebtoonPageHolder(
|
|||||||
/**
|
/**
|
||||||
* Creates a new progress bar.
|
* Creates a new progress bar.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("PrivateResource")
|
private fun createProgressIndicator(): ReaderProgressIndicator {
|
||||||
private fun createProgressBar(): ReaderProgressBar {
|
|
||||||
progressContainer = FrameLayout(context)
|
progressContainer = FrameLayout(context)
|
||||||
frame.addView(progressContainer, MATCH_PARENT, parentHeight)
|
frame.addView(progressContainer, MATCH_PARENT, parentHeight)
|
||||||
|
|
||||||
val progress = ReaderProgressBar(context).apply {
|
val progress = ReaderProgressIndicator(context).apply {
|
||||||
val size = 48.dpToPx
|
updateLayoutParams<FrameLayout.LayoutParams> {
|
||||||
layoutParams = FrameLayout.LayoutParams(size, size).apply {
|
|
||||||
gravity = Gravity.CENTER_HORIZONTAL
|
gravity = Gravity.CENTER_HORIZONTAL
|
||||||
setMargins(0, parentHeight / 4, 0, 0)
|
updateMargins(top = parentHeight / 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
progressContainer.addView(progress)
|
progressContainer.addView(progress)
|
||||||
|
@ -4,11 +4,11 @@ import android.view.Gravity
|
|||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.appcompat.widget.AppCompatButton
|
import androidx.appcompat.widget.AppCompatButton
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import androidx.appcompat.widget.AppCompatTextView
|
||||||
import androidx.core.view.isNotEmpty
|
import androidx.core.view.isNotEmpty
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
@ -111,7 +111,8 @@ class WebtoonTransitionHolder(
|
|||||||
* Sets the loading state on the pages container.
|
* Sets the loading state on the pages container.
|
||||||
*/
|
*/
|
||||||
private fun setLoading() {
|
private fun setLoading() {
|
||||||
val progress = ProgressBar(context, null, android.R.attr.progressBarStyle)
|
val progress = CircularProgressIndicator(context)
|
||||||
|
progress.isIndeterminate = true
|
||||||
|
|
||||||
val textView = AppCompatTextView(context).apply {
|
val textView = AppCompatTextView(context).apply {
|
||||||
wrapContent()
|
wrapContent()
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:indicatorSize="56dp"
|
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.ui.reader.PageIndicatorTextView
|
<eu.kanade.tachiyomi.ui.reader.PageIndicatorTextView
|
||||||
|
Loading…
Reference in New Issue
Block a user