From 46374e058214e4235356553fd8791a0d73c65e68 Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Fri, 26 Mar 2021 04:06:02 -0400 Subject: [PATCH] Animating swipe for category hopper So its more clear that it's swipeable --- .../tachiyomi/ui/library/LibraryController.kt | 20 +++- .../ui/library/LibraryGestureDetector.kt | 108 ++++++++++++------ .../kanade/tachiyomi/ui/main/MainActivity.kt | 4 +- 3 files changed, 96 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index ef6eeee438..93b873973a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -16,6 +16,7 @@ import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater import android.view.MenuItem +import android.view.MotionEvent import android.view.View import android.view.ViewGroup import android.view.ViewPropertyAnimator @@ -194,6 +195,7 @@ class LibraryController( private var filterTooltip: ViewTooltip? = null private var isAnimatingHopper: Boolean? = null + private var animatorSet: AnimatorSet? = null var hasMovedHopper = preferences.shownHopperSwipeTutorial().get() private var shouldScrollToTop = false private val showCategoryInTitle @@ -542,7 +544,7 @@ class LibraryController( } } - @SuppressLint("RtlHardcoded") + @SuppressLint("RtlHardcoded", "ClickableViewAccessibility") private fun setUpHopper() { category_hopper_frame.gone() down_category.setOnClickListener { @@ -598,7 +600,18 @@ class LibraryController( val gestureDetector = GestureDetectorCompat(activity, LibraryGestureDetector(this)) listOf(category_hopper_layout, up_category, down_category, category_button).forEach { it.setOnTouchListener { _, event -> - gestureDetector.onTouchEvent(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) + } } } } @@ -884,6 +897,7 @@ class LibraryController( isAnimatingHopper = true val slide = 25f.dpToPx val animatorSet = AnimatorSet() + this.animatorSet = animatorSet val animations = listOf( slideAnimation(0f, slide, 200), slideAnimation(slide, -slide), @@ -895,7 +909,9 @@ class LibraryController( animatorSet.startDelay = 1250 animatorSet.addListener( EndAnimatorListener { + category_hopper_frame.translationX = 0f isAnimatingHopper = false + this.animatorSet = null } ) animatorSet.start() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGestureDetector.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGestureDetector.kt index 64819328c2..7ae62cf62c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGestureDetector.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGestureDetector.kt @@ -4,12 +4,13 @@ import android.view.GestureDetector import android.view.Gravity import android.view.MotionEvent 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.updateLayoutParams import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.library_list_controller.* import kotlin.math.abs +import kotlin.math.pow +import kotlin.math.sign class LibraryGestureDetector(private val controller: LibraryController) : GestureDetector .SimpleOnGestureListener() { @@ -17,6 +18,22 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur 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( e1: MotionEvent, e2: MotionEvent, @@ -26,53 +43,80 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur var result = false val diffY = e2.y - e1.y 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) && - abs(diffY) > MainActivity.SWIPE_THRESHOLD && - abs(velocityY) > MainActivity.SWIPE_VELOCITY_THRESHOLD + abs(diffY) > SWIPE_THRESHOLD && + abs(velocityY) > SWIPE_VELOCITY_THRESHOLD ) { if (diffY <= 0) { controller.showSheet() } else { controller.filter_bottom_sheet.sheetBehavior?.hide() } - result = true } else if (abs(diffX) >= abs(diffY) && - abs(diffX) > MainActivity.SWIPE_THRESHOLD * 3 && - abs(velocityX) > MainActivity.SWIPE_VELOCITY_THRESHOLD + abs(diffX) > SWIPE_THRESHOLD * 5 && + abs(velocityX) > SWIPE_VELOCITY_THRESHOLD ) { + val hopperGravity = (controller.category_hopper_frame.layoutParams as CoordinatorLayout.LayoutParams).gravity if (diffX <= 0) { - controller.category_hopper_frame.updateLayoutParams { - gravity = - Gravity.TOP or ( - if (gravity == Gravity.TOP or Gravity.RIGHT) { - controller.preferences.hopperGravity().set(1) - Gravity.CENTER - } else { - controller.preferences.hopperGravity().set(0) - Gravity.LEFT - } - ) + 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 { + gravity = + Gravity.TOP or ( + if (gravity == Gravity.TOP or Gravity.RIGHT) { + controller.preferences.hopperGravity().set(1) + Gravity.CENTER + } else { + controller.preferences.hopperGravity().set(0) + Gravity.LEFT + } + ) + } + savePrefs() } } else { - controller.category_hopper_frame.updateLayoutParams { - gravity = - Gravity.TOP or ( - if (gravity == Gravity.TOP or Gravity.LEFT) { - controller.preferences.hopperGravity().set(1) - Gravity.CENTER - } else { - controller.preferences.hopperGravity().set(2) - Gravity.RIGHT - } - ) + 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 { + gravity = + Gravity.TOP or ( + if (gravity == Gravity.TOP or Gravity.LEFT) { + controller.preferences.hopperGravity().set(1) + Gravity.CENTER + } else { + controller.preferences.hopperGravity().set(2) + Gravity.RIGHT + } + ) + } + savePrefs() } } - if (!controller.hasMovedHopper) { - controller.preferences.shownHopperSwipeTutorial().set(true) - } - controller.hopperGravity = controller.preferences.hopperGravity().get() result = true } + animator.start() return result } + + fun savePrefs() { + if (!controller.hasMovedHopper) { + controller.preferences.shownHopperSwipeTutorial().set(true) + } + controller.hopperGravity = controller.preferences.hopperGravity().get() + controller.category_hopper_frame.translationX = 0f + } + + private companion object { + const val SWIPE_THRESHOLD = 50 + const val SWIPE_VELOCITY_THRESHOLD = 100 + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index dea05aca53..7451aa7740 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -682,8 +682,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener { companion object { - const val SWIPE_THRESHOLD = 100 - const val SWIPE_VELOCITY_THRESHOLD = 100 + private const val SWIPE_THRESHOLD = 100 + private const val SWIPE_VELOCITY_THRESHOLD = 100 // Shortcut actions const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY"