mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-09-11 14:03:20 +02:00
Parallax scrolling to Manga details page
This commit is contained in:
parent
0d658d4b05
commit
497f965cba
@ -35,6 +35,7 @@ import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.core.math.MathUtils
|
||||
import androidx.palette.graphics.Palette
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
@ -100,8 +101,6 @@ import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||
import kotlinx.android.synthetic.main.main_activity.*
|
||||
@ -110,6 +109,10 @@ import kotlinx.android.synthetic.main.manga_header_item.*
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
|
||||
class MangaDetailsController : BaseController,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
@ -214,14 +217,16 @@ class MangaDetailsController : BaseController,
|
||||
val appbarHeight = array.getDimensionPixelSize(0, 0)
|
||||
array.recycle()
|
||||
val offset = 10.dpToPx
|
||||
var statusBarHeight = -1
|
||||
|
||||
recycler.doOnApplyWindowInsets { v, insets, _ ->
|
||||
headerHeight = appbarHeight + insets.systemWindowInsetTop
|
||||
statusBarHeight = insets.systemWindowInsetTop
|
||||
swipe_refresh.setProgressViewOffset(false, (-40).dpToPx, headerHeight + offset)
|
||||
(recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder)
|
||||
?.setTopHeight(headerHeight)
|
||||
fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = headerHeight
|
||||
topMargin = statusBarHeight
|
||||
bottomMargin = insets.systemWindowInsetBottom
|
||||
}
|
||||
v.updatePaddingRelative(bottom = insets.systemWindowInsetBottom)
|
||||
@ -233,36 +238,42 @@ class MangaDetailsController : BaseController,
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
val atTop = !recycler.canScrollVertically(-1)
|
||||
if ((!atTop && !toolbarIsColored) || (atTop && toolbarIsColored)) {
|
||||
toolbarIsColored = !atTop
|
||||
val isCurrentController =
|
||||
router?.backstack?.lastOrNull()?.controller() == this@MangaDetailsController
|
||||
if (isCurrentController) setTitle()
|
||||
if (actionMode != null) {
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
return
|
||||
}
|
||||
val color =
|
||||
coverColor ?: activity!!.getResourceColor(R.attr.colorPrimaryVariant)
|
||||
val colorFrom =
|
||||
if (colorAnimator?.isRunning == true) activity?.window?.statusBarColor
|
||||
?: color
|
||||
else ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 0 else 175
|
||||
)
|
||||
val colorTo = ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 175 else 0
|
||||
val tY = getHeader()?.backdrop?.translationY ?: 0f
|
||||
getHeader()?.backdrop?.translationY = max(0f, tY + dy * 0.25f)
|
||||
if (router?.backstack?.lastOrNull()
|
||||
?.controller() == this@MangaDetailsController && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0
|
||||
) {
|
||||
activity!!.appbar.y -= dy
|
||||
activity!!.appbar.y = MathUtils.clamp(
|
||||
activity!!.appbar.y, -activity!!.appbar.height.toFloat(), 0f
|
||||
)
|
||||
colorAnimator?.cancel()
|
||||
colorAnimator = ValueAnimator.ofObject(
|
||||
android.animation.ArgbEvaluator(), colorFrom, colorTo
|
||||
)
|
||||
colorAnimator?.duration = 250 // milliseconds
|
||||
colorAnimator?.addUpdateListener { animator ->
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(animator.animatedValue as Int)
|
||||
activity?.window?.statusBarColor = (animator.animatedValue as Int)
|
||||
}
|
||||
val appBarY = activity?.appbar?.y ?: 0f
|
||||
if ((!atTop && !toolbarIsColored && (appBarY < (-headerHeight + 1) || (dy < 0 && appBarY == 0f))) || (atTop && toolbarIsColored)) {
|
||||
colorToolbar(!atTop)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
super.onScrollStateChanged(recyclerView, newState)
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
if (router?.backstack?.lastOrNull()
|
||||
?.controller() == this@MangaDetailsController && statusBarHeight > -1 && activity != null &&
|
||||
activity!!.appbar.height > 0
|
||||
) {
|
||||
val halfWay = abs((-activity!!.appbar.height.toFloat()) / 2)
|
||||
val shortAnimationDuration = resources?.getInteger(
|
||||
android.R.integer.config_shortAnimTime
|
||||
) ?: 0
|
||||
val closerToTop = abs(activity!!.appbar.y) - halfWay > 0
|
||||
val atTop = !recycler.canScrollVertically(-1)
|
||||
activity!!.appbar.animate().y(
|
||||
if (closerToTop && !atTop) (-activity!!.appbar.height.toFloat())
|
||||
else 0f
|
||||
).setDuration(shortAnimationDuration.toLong()).start()
|
||||
if (!closerToTop && !atTop && !toolbarIsColored)
|
||||
colorToolbar(true)
|
||||
}
|
||||
colorAnimator?.start()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -275,6 +286,38 @@ class MangaDetailsController : BaseController,
|
||||
swipe_refresh.setOnRefreshListener { presenter.refreshAll() }
|
||||
}
|
||||
|
||||
fun colorToolbar(isColor: Boolean) {
|
||||
toolbarIsColored = isColor
|
||||
val isCurrentController =
|
||||
router?.backstack?.lastOrNull()?.controller() == this@MangaDetailsController
|
||||
if (isCurrentController) setTitle()
|
||||
if (actionMode != null) {
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(Color.TRANSPARENT)
|
||||
return
|
||||
}
|
||||
val color =
|
||||
coverColor ?: activity!!.getResourceColor(R.attr.colorPrimaryVariant)
|
||||
val colorFrom =
|
||||
if (colorAnimator?.isRunning == true) activity?.window?.statusBarColor
|
||||
?: color
|
||||
else ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 0 else 175
|
||||
)
|
||||
val colorTo = ColorUtils.setAlphaComponent(
|
||||
color, if (toolbarIsColored) 175 else 0
|
||||
)
|
||||
colorAnimator?.cancel()
|
||||
colorAnimator = ValueAnimator.ofObject(
|
||||
android.animation.ArgbEvaluator(), colorFrom, colorTo
|
||||
)
|
||||
colorAnimator?.duration = 250 // milliseconds
|
||||
colorAnimator?.addUpdateListener { animator ->
|
||||
(activity as MainActivity).toolbar.setBackgroundColor(animator.animatedValue as Int)
|
||||
activity?.window?.statusBarColor = (animator.animatedValue as Int)
|
||||
}
|
||||
colorAnimator?.start()
|
||||
}
|
||||
|
||||
fun setPaletteColor() {
|
||||
val view = view ?: return
|
||||
GlideApp.with(view.context).load(manga)
|
||||
@ -345,6 +388,8 @@ class MangaDetailsController : BaseController,
|
||||
return recycler?.findViewHolderForItemId(chapter.id!!) as? ChapterHolder
|
||||
}
|
||||
|
||||
private fun getHeader(): MangaHeaderHolder? = recycler.findViewHolderForAdapterPosition(0) as? MangaHeaderHolder
|
||||
|
||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||
super.onChangeStarted(handler, type)
|
||||
if (type == ControllerChangeType.PUSH_ENTER || type == ControllerChangeType.POP_ENTER) {
|
||||
|
@ -38,6 +38,13 @@
|
||||
android:backgroundTint="?android:attr/colorBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/true_backdrop" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/colorBackground"
|
||||
app:layout_constraintTop_toBottomOf="@id/backdrop_gradient"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/top_view"
|
||||
android:layout_width="match_parent"
|
||||
|
Loading…
Reference in New Issue
Block a user