Animating swipe for category hopper

So its more clear that it's swipeable
This commit is contained in:
Jays2Kings 2021-03-26 04:06:02 -04:00
parent 28f5a6986f
commit 46374e0582
3 changed files with 96 additions and 36 deletions

View File

@ -16,6 +16,7 @@ import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewPropertyAnimator import android.view.ViewPropertyAnimator
@ -194,6 +195,7 @@ class LibraryController(
private var filterTooltip: ViewTooltip? = null private var filterTooltip: ViewTooltip? = null
private var isAnimatingHopper: Boolean? = null private var isAnimatingHopper: Boolean? = null
private var animatorSet: AnimatorSet? = null
var hasMovedHopper = preferences.shownHopperSwipeTutorial().get() var hasMovedHopper = preferences.shownHopperSwipeTutorial().get()
private var shouldScrollToTop = false private var shouldScrollToTop = false
private val showCategoryInTitle private val showCategoryInTitle
@ -542,7 +544,7 @@ class LibraryController(
} }
} }
@SuppressLint("RtlHardcoded") @SuppressLint("RtlHardcoded", "ClickableViewAccessibility")
private fun setUpHopper() { private fun setUpHopper() {
category_hopper_frame.gone() category_hopper_frame.gone()
down_category.setOnClickListener { down_category.setOnClickListener {
@ -598,10 +600,21 @@ class LibraryController(
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 {
it.setOnTouchListener { _, event -> it.setOnTouchListener { _, event ->
if (event?.action == MotionEvent.ACTION_DOWN) {
animatorSet?.end()
}
if (event?.action == MotionEvent.ACTION_UP) {
val result = gestureDetector.onTouchEvent(event)
if (!result) {
category_hopper_frame.animate().setDuration(150L).translationX(0f).start()
}
result
} else {
gestureDetector.onTouchEvent(event) gestureDetector.onTouchEvent(event)
} }
} }
} }
}
fun updateHopperY() { fun updateHopperY() {
val view = view ?: return val view = view ?: return
@ -884,6 +897,7 @@ class LibraryController(
isAnimatingHopper = true isAnimatingHopper = true
val slide = 25f.dpToPx val slide = 25f.dpToPx
val animatorSet = AnimatorSet() val animatorSet = AnimatorSet()
this.animatorSet = animatorSet
val animations = listOf( val animations = listOf(
slideAnimation(0f, slide, 200), slideAnimation(0f, slide, 200),
slideAnimation(slide, -slide), slideAnimation(slide, -slide),
@ -895,7 +909,9 @@ class LibraryController(
animatorSet.startDelay = 1250 animatorSet.startDelay = 1250
animatorSet.addListener( animatorSet.addListener(
EndAnimatorListener { EndAnimatorListener {
category_hopper_frame.translationX = 0f
isAnimatingHopper = false isAnimatingHopper = false
this.animatorSet = null
} }
) )
animatorSet.start() animatorSet.start()

View File

@ -4,12 +4,13 @@ import android.view.GestureDetector
import android.view.Gravity import android.view.Gravity
import android.view.MotionEvent import android.view.MotionEvent
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.view.hide import eu.kanade.tachiyomi.util.view.hide
import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updateLayoutParams
import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.filter_bottom_sheet.*
import kotlinx.android.synthetic.main.library_list_controller.* import kotlinx.android.synthetic.main.library_list_controller.*
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sign
class LibraryGestureDetector(private val controller: LibraryController) : GestureDetector class LibraryGestureDetector(private val controller: LibraryController) : GestureDetector
.SimpleOnGestureListener() { .SimpleOnGestureListener() {
@ -17,6 +18,22 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
return false return false
} }
override fun onScroll(
e1: MotionEvent?,
e2: MotionEvent?,
distanceX: Float,
distanceY: Float
): Boolean {
val distance = ((e1?.rawX ?: 0f) - (e2?.rawX ?: 0f)) / 50
val poa = 1.7f
controller.category_hopper_frame.translationX = abs(distance).pow(poa) * -sign(distance)
return super.onScroll(e1, e2, distanceX, distanceY)
}
override fun onSingleTapUp(e: MotionEvent?): Boolean {
return super.onSingleTapUp(e)
}
override fun onFling( override fun onFling(
e1: MotionEvent, e1: MotionEvent,
e2: MotionEvent, e2: MotionEvent,
@ -26,21 +43,30 @@ 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
val animator = controller.category_hopper_frame.animate().setDuration(150L)
animator.translationX(0f)
animator.withEndAction {
controller.category_hopper_frame.translationX = 0f
}
if (abs(diffX) <= abs(diffY) && if (abs(diffX) <= abs(diffY) &&
abs(diffY) > MainActivity.SWIPE_THRESHOLD && abs(diffY) > SWIPE_THRESHOLD &&
abs(velocityY) > MainActivity.SWIPE_VELOCITY_THRESHOLD abs(velocityY) > 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
} else if (abs(diffX) >= abs(diffY) && } else if (abs(diffX) >= abs(diffY) &&
abs(diffX) > MainActivity.SWIPE_THRESHOLD * 3 && abs(diffX) > SWIPE_THRESHOLD * 5 &&
abs(velocityX) > MainActivity.SWIPE_VELOCITY_THRESHOLD abs(velocityX) > SWIPE_VELOCITY_THRESHOLD
) { ) {
val hopperGravity = (controller.category_hopper_frame.layoutParams as CoordinatorLayout.LayoutParams).gravity
if (diffX <= 0) { if (diffX <= 0) {
animator.translationX(
if (hopperGravity == Gravity.TOP or Gravity.LEFT) 0f
else (-(controller.view!!.width - controller.category_hopper_frame.width) / 2).toFloat()
).withEndAction {
controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> { controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> {
gravity = gravity =
Gravity.TOP or ( Gravity.TOP or (
@ -53,7 +79,13 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
} }
) )
} }
savePrefs()
}
} else { } else {
animator.translationX(
if (hopperGravity == Gravity.TOP or Gravity.RIGHT) 0f
else ((controller.view!!.width - controller.category_hopper_frame.width) / 2).toFloat()
).withEndAction {
controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> { controller.category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> {
gravity = gravity =
Gravity.TOP or ( Gravity.TOP or (
@ -66,13 +98,25 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
} }
) )
} }
savePrefs()
} }
}
result = true
}
animator.start()
return result
}
fun savePrefs() {
if (!controller.hasMovedHopper) { if (!controller.hasMovedHopper) {
controller.preferences.shownHopperSwipeTutorial().set(true) controller.preferences.shownHopperSwipeTutorial().set(true)
} }
controller.hopperGravity = controller.preferences.hopperGravity().get() controller.hopperGravity = controller.preferences.hopperGravity().get()
result = true controller.category_hopper_frame.translationX = 0f
} }
return result
private companion object {
const val SWIPE_THRESHOLD = 50
const val SWIPE_VELOCITY_THRESHOLD = 100
} }
} }

View File

@ -682,8 +682,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
companion object { companion object {
const val SWIPE_THRESHOLD = 100 private const val SWIPE_THRESHOLD = 100
const val SWIPE_VELOCITY_THRESHOLD = 100 private const val SWIPE_VELOCITY_THRESHOLD = 100
// Shortcut actions // Shortcut actions
const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY" const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY"