Added tutorial to show you can move the category hopper

Let's see how many questions I get saying "why is it shaking and moving around"
This commit is contained in:
Jay 2020-05-08 01:35:50 -04:00
parent 1cc31049c1
commit 1c9cb7644c
3 changed files with 60 additions and 24 deletions

View File

@ -275,4 +275,6 @@ class PreferencesHelper(val context: Context) {
fun shownDownloadQueueTutorial() = flowPrefs.getBoolean("shown_download_queue", false) fun shownDownloadQueueTutorial() = flowPrefs.getBoolean("shown_download_queue", false)
fun shownLongPressCategoryTutorial() = flowPrefs.getBoolean("shown_long_press_category", false) fun shownLongPressCategoryTutorial() = flowPrefs.getBoolean("shown_long_press_category", false)
fun shownHopperSwipeTutorial() = flowPrefs.getBoolean("shown_hopper_swipe", false)
} }

View File

@ -1,5 +1,7 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
@ -75,6 +77,7 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.visibleIf import eu.kanade.tachiyomi.util.view.visibleIf
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.EndAnimatorListener
import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.filter_bottom_sheet.*
import kotlinx.android.synthetic.main.library_grid_recycler.* import kotlinx.android.synthetic.main.library_grid_recycler.*
import kotlinx.android.synthetic.main.library_list_controller.* import kotlinx.android.synthetic.main.library_list_controller.*
@ -85,6 +88,8 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.random.Random
import kotlin.random.nextInt
class LibraryController( class LibraryController(
bundle: Bundle? = null, bundle: Bundle? = null,
@ -106,9 +111,6 @@ class LibraryController(
* Position of the active category. * Position of the active category.
*/ */
private var activeCategory: Int = preferences.lastUsedCategory().getOrDefault() private var activeCategory: Int = preferences.lastUsedCategory().getOrDefault()
set(value) {
field = value
}
private var justStarted = true private var justStarted = true
@ -148,7 +150,6 @@ class LibraryController(
private var scrollDistance = 0f private var scrollDistance = 0f
private val scrollDistanceTilHidden = 1000.dpToPx private val scrollDistanceTilHidden = 1000.dpToPx
private var textAnim: ViewPropertyAnimator? = null private var textAnim: ViewPropertyAnimator? = null
var hopperGravity: Int = preferences.hopperGravity().get() var hopperGravity: Int = preferences.hopperGravity().get()
set(value) { set(value) {
@ -165,6 +166,8 @@ class LibraryController(
} }
private var filterTooltip: ViewTooltip? = null private var filterTooltip: ViewTooltip? = null
private var isAnimatingHopper: Boolean? = null
var hasMovedHopper = preferences.shownHopperSwipeTutorial().get()
private var elevationAnim: ValueAnimator? = null private var elevationAnim: ValueAnimator? = null
private var elevate = false private var elevate = false
@ -178,7 +181,7 @@ class LibraryController(
val notAtTop = recycler.canScrollVertically(-1) val notAtTop = recycler.canScrollVertically(-1)
if (notAtTop != elevate) elevateFunc(notAtTop) if (notAtTop != elevate) elevateFunc(notAtTop)
val order = getCategoryOrder() val order = getCategoryOrder()
if (!recycler_cover.isClickable) { if (!recycler_cover.isClickable && isAnimatingHopper != true) {
category_hopper_frame.translationY += dy category_hopper_frame.translationY += dy
category_hopper_frame.translationY = category_hopper_frame.translationY =
category_hopper_frame.translationY.coerceIn(0f, 60f.dpToPx) category_hopper_frame.translationY.coerceIn(0f, 60f.dpToPx)
@ -338,14 +341,19 @@ class LibraryController(
true true
} }
val gravityPref = if (!hasMovedHopper) {
Random.nextInt(0..2)
} else {
preferences.hopperGravity().get()
}
category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> { category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> {
anchorGravity = Gravity.TOP or when (preferences.hopperGravity().get()) { anchorGravity = Gravity.TOP or when (gravityPref) {
0 -> Gravity.LEFT 0 -> Gravity.LEFT
2 -> Gravity.RIGHT 2 -> Gravity.RIGHT
else -> Gravity.CENTER else -> Gravity.CENTER
} }
} }
hopperGravity = preferences.hopperGravity().get() hopperGravity = gravityPref
val gestureDetector = GestureDetectorCompat(activity, LibraryGestureDetector(this)) val gestureDetector = GestureDetectorCompat(activity, LibraryGestureDetector(this))
listOf(category_hopper_layout, up_category, down_category, category_button).forEach { listOf(category_hopper_layout, up_category, down_category, category_button).forEach {
@ -358,9 +366,6 @@ class LibraryController(
category_layout?.updateLayoutParams<ViewGroup.MarginLayoutParams> { category_layout?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = recycler?.paddingTop ?: 0 topMargin = recycler?.paddingTop ?: 0
} }
// fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
// topMargin = insets.systemWindowInsetTop
// }
}) })
swipe_refresh.setOnRefreshListener { swipe_refresh.setOnRefreshListener {
@ -647,8 +652,35 @@ class LibraryController(
showCategories(recycler.translationY == 0f) showCategories(recycler.translationY == 0f)
} }
} }
if (!hasMovedHopper && isAnimatingHopper == null) {
showSlideAnimation()
} }
} }
}
private fun showSlideAnimation() {
isAnimatingHopper = true
val slide = 25f.dpToPx
val animatorSet = AnimatorSet()
val animations = listOf(
slideAnimation(0f, slide, 200),
slideAnimation(slide, -slide),
slideAnimation(-slide, slide),
slideAnimation(slide, -slide),
slideAnimation(-slide, 0f, 233)
)
animatorSet.playSequentially(animations)
animatorSet.startDelay = 1250
animatorSet.addListener(EndAnimatorListener {
isAnimatingHopper = false
})
animatorSet.start()
}
private fun slideAnimation(from: Float, to: Float, duration: Long = 400): ObjectAnimator {
return ObjectAnimator.ofFloat(category_hopper_frame, View.TRANSLATION_X, from, to)
.setDuration(duration)
}
private fun showCategories(show: Boolean, scroll: Boolean = true) { private fun showCategories(show: Boolean, scroll: Boolean = true) {
recycler_cover.isClickable = show recycler_cover.isClickable = show

View File

@ -26,18 +26,17 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
var result = false var result = false
val diffY = e2.y - e1.y val diffY = e2.y - e1.y
val diffX = e2.x - e1.x val diffX = e2.x - e1.x
if (abs(diffX) <= abs(diffY) && if (abs(diffX) <= abs(diffY) && abs(diffY) > MainActivity.SWIPE_THRESHOLD && abs(velocityY) > MainActivity.SWIPE_VELOCITY_THRESHOLD) {
abs(diffY) > MainActivity.SWIPE_THRESHOLD &&
abs(velocityY) > MainActivity.SWIPE_VELOCITY_THRESHOLD) {
if (diffY <= 0) { if (diffY <= 0) {
controller.showSheet() controller.showSheet()
} else { } else {
controller.filter_bottom_sheet.sheetBehavior?.hide() controller.filter_bottom_sheet.sheetBehavior?.hide()
} }
result = true result = true
} else if (abs(diffX) >= abs(diffY) && } else if (abs(diffX) >= abs(diffY) && abs(diffX) > MainActivity.SWIPE_THRESHOLD && abs(
abs(diffX) > MainActivity.SWIPE_THRESHOLD && velocityX
abs(velocityX) > MainActivity.SWIPE_VELOCITY_THRESHOLD) { ) > MainActivity.SWIPE_VELOCITY_THRESHOLD
) {
// val transition = androidx.transition.AutoTransition() // val transition = androidx.transition.AutoTransition()
// transition.duration = 150 // transition.duration = 150
@ -57,8 +56,8 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
} }
} else { } else {
controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> { controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> {
anchorGravity = Gravity.TOP or anchorGravity =
Gravity.TOP or (if (anchorGravity == Gravity.TOP or Gravity.LEFT) { Gravity.TOP or Gravity.TOP or (if (anchorGravity == Gravity.TOP or Gravity.LEFT) {
controller.preferences.hopperGravity().set(1) controller.preferences.hopperGravity().set(1)
Gravity.CENTER Gravity.CENTER
} else { } else {
@ -67,6 +66,9 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
}) })
} }
} }
if (!controller.hasMovedHopper) {
controller.preferences.shownHopperSwipeTutorial().set(true)
}
controller.hopperGravity = controller.preferences.hopperGravity().get() controller.hopperGravity = controller.preferences.hopperGravity().get()
result = true result = true
} }