feat: scroll app list from anywhere on screen; gate search item animation
DrawFragment: app-list touch area now forwards vertical drags/flings to the drawer RecyclerView, so the list scrolls even when grabbing empty space right of the app names. OnSwipeTouchListener gained no-op vertical scroll and fling hooks. When animations are disabled, drop the RecyclerView item animator so DiffUtil search updates no longer pan entries up into place.
This commit is contained in:
@@ -90,6 +90,7 @@ internal open class OnSwipeTouchListener(context: Context?, private val preferen
|
||||
}
|
||||
// Vertical swipe
|
||||
else {
|
||||
onVerticalScroll(distanceY)
|
||||
if (abs(diffY) > swipeThreshold && abs(distanceY) > swipeScrollThreshold) {
|
||||
if (diffY > 0) onSwipeDown() else onSwipeUp()
|
||||
}
|
||||
@@ -115,6 +116,7 @@ internal open class OnSwipeTouchListener(context: Context?, private val preferen
|
||||
}
|
||||
} else {
|
||||
if (abs(diffY) > swipeThreshold && abs(velocityY) > swipeVelocityThreshold) {
|
||||
onVerticalFling(velocityY)
|
||||
if (diffY < 0) onSwipeUp() else onSwipeDown()
|
||||
}
|
||||
}
|
||||
@@ -129,6 +131,21 @@ internal open class OnSwipeTouchListener(context: Context?, private val preferen
|
||||
open fun onSwipeLeft() {}
|
||||
open fun onSwipeUp() {}
|
||||
open fun onSwipeDown() {}
|
||||
|
||||
/**
|
||||
* Called for every vertical drag movement (per-event delta, same sign
|
||||
* convention as RecyclerView's own touch handling: positive when the
|
||||
* finger moves up). Default is a no-op.
|
||||
*/
|
||||
open fun onVerticalScroll(distanceY: Float) {}
|
||||
|
||||
/**
|
||||
* Called on a vertical fling with the raw pointer velocity in pixels per
|
||||
* second (positive when the finger moved down, same convention as
|
||||
* VelocityTracker.getYVelocity()). Default is a no-op.
|
||||
*/
|
||||
open fun onVerticalFling(velocityY: Float) {}
|
||||
|
||||
open fun onLongClick() {}
|
||||
open fun onDoubleClick() {}
|
||||
open fun onTripleClick() {}
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.github.droidworksstudio.launcher.helper.PreferenceHelper
|
||||
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
|
||||
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
|
||||
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
|
||||
import kotlin.math.roundToInt
|
||||
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
|
||||
import com.github.droidworksstudio.launcher.utils.Constants
|
||||
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
|
||||
@@ -157,6 +158,11 @@ class DrawFragment : Fragment(),
|
||||
setHasFixedSize(false)
|
||||
layoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
|
||||
isNestedScrollingEnabled = false
|
||||
|
||||
// Search results update the list with DiffUtil. When animations
|
||||
// are disabled, drop the item animator so entries don't "pan-up"
|
||||
// into place while filtering.
|
||||
if (preferenceHelper.disableAnimations) itemAnimator = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +243,7 @@ class DrawFragment : Fragment(),
|
||||
binding.apply {
|
||||
mainView.setOnTouchListener(getSwipeGestureListener(context))
|
||||
touchArea.setOnTouchListener(getSwipeGestureListener(context))
|
||||
appListTouchArea.setOnTouchListener(getSwipeGestureListener(context))
|
||||
appListTouchArea.setOnTouchListener(getAppListSwipeGestureListener(context))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,36 +308,65 @@ class DrawFragment : Fragment(),
|
||||
return object : OnSwipeTouchListener(context, preferenceHelper) {
|
||||
override fun onSwipeLeft() {
|
||||
super.onSwipeLeft()
|
||||
val actionTypeNavOptions: NavOptions? =
|
||||
if (preferenceHelper.disableAnimations) null
|
||||
else appHelper.getActionType(Constants.Swipe.Left)
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
findNavController().navigate(
|
||||
R.id.HomeFragment,
|
||||
null,
|
||||
actionTypeNavOptions
|
||||
)
|
||||
}
|
||||
navigateToHome(Constants.Swipe.Left)
|
||||
}
|
||||
|
||||
override fun onSwipeRight() {
|
||||
super.onSwipeRight()
|
||||
val actionTypeNavOptions: NavOptions? =
|
||||
if (preferenceHelper.disableAnimations) null
|
||||
else appHelper.getActionType(Constants.Swipe.Right)
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
findNavController().navigate(
|
||||
R.id.HomeFragment,
|
||||
null,
|
||||
actionTypeNavOptions
|
||||
)
|
||||
}
|
||||
navigateToHome(Constants.Swipe.Right)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swipe listener for the app list area.
|
||||
*
|
||||
* Behaves like [getSwipeGestureListener] (left/right swipes navigate
|
||||
* home), but vertical drags and flings over the empty space around the
|
||||
* list (e.g. right of the app names) scroll the list itself. This makes
|
||||
* the drawer scrollable from the whole screen, not just the app rows.
|
||||
*/
|
||||
private fun getAppListSwipeGestureListener(context: Context): View.OnTouchListener {
|
||||
return object : OnSwipeTouchListener(context, preferenceHelper) {
|
||||
override fun onSwipeLeft() {
|
||||
super.onSwipeLeft()
|
||||
navigateToHome(Constants.Swipe.Left)
|
||||
}
|
||||
|
||||
override fun onSwipeRight() {
|
||||
super.onSwipeRight()
|
||||
navigateToHome(Constants.Swipe.Right)
|
||||
}
|
||||
|
||||
override fun onVerticalScroll(distanceY: Float) {
|
||||
super.onVerticalScroll(distanceY)
|
||||
binding.drawAdapter.scrollBy(0, distanceY.roundToInt())
|
||||
}
|
||||
|
||||
override fun onVerticalFling(velocityY: Float) {
|
||||
super.onVerticalFling(velocityY)
|
||||
// RecyclerView.fling expects the negated pointer velocity
|
||||
// (the same negation RecyclerView applies to its own
|
||||
// VelocityTracker value in onTouchEvent).
|
||||
binding.drawAdapter.fling(0, -velocityY.roundToInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToHome(swipe: Constants.Swipe) {
|
||||
val actionTypeNavOptions: NavOptions? =
|
||||
if (preferenceHelper.disableAnimations) null
|
||||
else appHelper.getActionType(swipe)
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
findNavController().navigate(
|
||||
R.id.HomeFragment,
|
||||
null,
|
||||
actionTypeNavOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the fuzzy search synchronously over the in-memory index.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user