Handle home screen pages dragging
This commit is contained in:
parent
47a92c3b66
commit
95cf8c0384
|
@ -60,6 +60,8 @@ class MainActivity : SimpleActivity(), FlingListener {
|
||||||
private var mMoveGestureThreshold = 0
|
private var mMoveGestureThreshold = 0
|
||||||
private var mIgnoreUpEvent = false
|
private var mIgnoreUpEvent = false
|
||||||
private var mIgnoreMoveEvents = false
|
private var mIgnoreMoveEvents = false
|
||||||
|
private var mIgnoreXMoveEvents = false
|
||||||
|
private var mIgnoreYMoveEvents = false
|
||||||
private var mLongPressedIcon: HomeScreenGridItem? = null
|
private var mLongPressedIcon: HomeScreenGridItem? = null
|
||||||
private var mOpenPopupMenu: PopupMenu? = null
|
private var mOpenPopupMenu: PopupMenu? = null
|
||||||
private var mCachedLaunchers = ArrayList<AppLauncher>()
|
private var mCachedLaunchers = ArrayList<AppLauncher>()
|
||||||
|
@ -362,13 +364,20 @@ class MainActivity : SimpleActivity(), FlingListener {
|
||||||
|
|
||||||
if (hasFingerMoved && !mIgnoreMoveEvents) {
|
if (hasFingerMoved && !mIgnoreMoveEvents) {
|
||||||
val diffY = mTouchDownY - event.y
|
val diffY = mTouchDownY - event.y
|
||||||
|
val diffX = mTouchDownX - event.x
|
||||||
|
|
||||||
if (isWidgetsFragmentExpanded()) {
|
if (abs(diffY) > abs(diffX) && !mIgnoreYMoveEvents) {
|
||||||
val newY = mWidgetsFragmentY - diffY
|
mIgnoreXMoveEvents = true
|
||||||
binding.widgetsFragment.root.y = Math.min(Math.max(0f, newY), mScreenHeight.toFloat())
|
if (isWidgetsFragmentExpanded()) {
|
||||||
} else if (mLongPressedIcon == null) {
|
val newY = mWidgetsFragmentY - diffY
|
||||||
val newY = mAllAppsFragmentY - diffY
|
binding.widgetsFragment.root.y = Math.min(Math.max(0f, newY), mScreenHeight.toFloat())
|
||||||
binding.allAppsFragment.root.y = Math.min(Math.max(0f, newY), mScreenHeight.toFloat())
|
} else if (mLongPressedIcon == null) {
|
||||||
|
val newY = mAllAppsFragmentY - diffY
|
||||||
|
binding.allAppsFragment.root.y = Math.min(Math.max(0f, newY), mScreenHeight.toFloat())
|
||||||
|
}
|
||||||
|
} else if (abs(diffX) > abs(diffY) && !mIgnoreXMoveEvents) {
|
||||||
|
mIgnoreYMoveEvents = true
|
||||||
|
binding.homeScreenGrid.root.setSwipeMovement(diffX)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,18 +395,27 @@ class MainActivity : SimpleActivity(), FlingListener {
|
||||||
binding.homeScreenGrid.root.itemDraggingStopped()
|
binding.homeScreenGrid.root.itemDraggingStopped()
|
||||||
|
|
||||||
if (!mIgnoreUpEvent) {
|
if (!mIgnoreUpEvent) {
|
||||||
if (binding.allAppsFragment.root.y < mScreenHeight * 0.5) {
|
if (!mIgnoreYMoveEvents) {
|
||||||
showFragment(binding.allAppsFragment)
|
if (binding.allAppsFragment.root.y < mScreenHeight * 0.5) {
|
||||||
} else if (isAllAppsFragmentExpanded()) {
|
showFragment(binding.allAppsFragment)
|
||||||
hideFragment(binding.allAppsFragment)
|
} else if (isAllAppsFragmentExpanded()) {
|
||||||
|
hideFragment(binding.allAppsFragment)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binding.widgetsFragment.root.y < mScreenHeight * 0.5) {
|
||||||
|
showFragment(binding.widgetsFragment)
|
||||||
|
} else if (isWidgetsFragmentExpanded()) {
|
||||||
|
hideFragment(binding.widgetsFragment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binding.widgetsFragment.root.y < mScreenHeight * 0.5) {
|
if (!mIgnoreXMoveEvents) {
|
||||||
showFragment(binding.widgetsFragment)
|
binding.homeScreenGrid.root.finalizeSwipe()
|
||||||
} else if (isWidgetsFragmentExpanded()) {
|
|
||||||
hideFragment(binding.widgetsFragment)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mIgnoreXMoveEvents = false
|
||||||
|
mIgnoreYMoveEvents = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,7 @@ import com.simplemobiletools.launcher.extensions.getDrawableForPackageName
|
||||||
import com.simplemobiletools.launcher.extensions.homeScreenGridItemsDB
|
import com.simplemobiletools.launcher.extensions.homeScreenGridItemsDB
|
||||||
import com.simplemobiletools.launcher.helpers.*
|
import com.simplemobiletools.launcher.helpers.*
|
||||||
import com.simplemobiletools.launcher.models.HomeScreenGridItem
|
import com.simplemobiletools.launcher.models.HomeScreenGridItem
|
||||||
import kotlin.math.abs
|
import kotlin.math.*
|
||||||
import kotlin.math.floor
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : RelativeLayout(context, attrs, defStyle) {
|
class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : RelativeLayout(context, attrs, defStyle) {
|
||||||
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
|
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
|
||||||
|
@ -77,6 +74,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
private var pageChangeAnimLeftPercentage = 0f
|
private var pageChangeAnimLeftPercentage = 0f
|
||||||
private var pageChangeEnabled = true
|
private var pageChangeEnabled = true
|
||||||
private var pageChangeIndicatorsAlpha = 0f
|
private var pageChangeIndicatorsAlpha = 0f
|
||||||
|
private var pageChangeSwipedPercentage = 0f
|
||||||
|
|
||||||
// apply fake margins at the home screen. Real ones would cause the icons be cut at dragging at screen sides
|
// apply fake margins at the home screen. Real ones would cause the icons be cut at dragging at screen sides
|
||||||
var sideMargins = Rect()
|
var sideMargins = Rect()
|
||||||
|
@ -611,21 +609,12 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
|
|
||||||
private fun updateWidgetPositionAndSize(widgetView: AppWidgetHostView, item: HomeScreenGridItem): Size {
|
private fun updateWidgetPositionAndSize(widgetView: AppWidgetHostView, item: HomeScreenGridItem): Size {
|
||||||
var x = calculateWidgetX(item.left) + width * item.page - width * lastPage
|
var x = calculateWidgetX(item.left) + width * item.page - width * lastPage
|
||||||
if (pageChangeAnimLeftPercentage > 0f && pageChangeAnimLeftPercentage < 1f && (item.page == currentPage || item.page == lastPage)) {
|
if (isBetweenPages() && (item.page == currentPage || item.page == lastPage || (pageChangeSwipedPercentage > 0f && item.page == currentPage - 1) || (pageChangeSwipedPercentage < 0f && item.page == currentPage + 1))) {
|
||||||
val xFactor = if (currentPage > lastPage) {
|
val xFactor = getXFactorForCurrentPage()
|
||||||
pageChangeAnimLeftPercentage
|
val lastXFactor = getXFactorForLastPage()
|
||||||
} else {
|
|
||||||
-pageChangeAnimLeftPercentage
|
|
||||||
}
|
|
||||||
val lastXFactor = if (currentPage > lastPage) {
|
|
||||||
pageChangeAnimLeftPercentage - 1
|
|
||||||
} else {
|
|
||||||
1 - pageChangeAnimLeftPercentage
|
|
||||||
}
|
|
||||||
if (item.page == currentPage) {
|
if (item.page == currentPage) {
|
||||||
x += width * xFactor
|
x += width * xFactor
|
||||||
}
|
} else if (item.page == lastPage || (pageChangeSwipedPercentage > 0f && item.page == currentPage - 1) || (pageChangeSwipedPercentage < 0f && item.page == currentPage + 1)) {
|
||||||
if (item.page == lastPage) {
|
|
||||||
x += width * lastXFactor
|
x += width * lastXFactor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,16 +674,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
fillCellSizes()
|
fillCellSizes()
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentXFactor = if (currentPage > lastPage) {
|
val currentXFactor = getXFactorForCurrentPage()
|
||||||
pageChangeAnimLeftPercentage
|
val lastXFactor = getXFactorForLastPage()
|
||||||
} else {
|
|
||||||
-pageChangeAnimLeftPercentage
|
|
||||||
}
|
|
||||||
val lastXFactor = if (currentPage > lastPage) {
|
|
||||||
pageChangeAnimLeftPercentage - 1
|
|
||||||
} else {
|
|
||||||
1 - pageChangeAnimLeftPercentage
|
|
||||||
}
|
|
||||||
|
|
||||||
fun handleItemDrawing(item: HomeScreenGridItem, xFactor: Float) {
|
fun handleItemDrawing(item: HomeScreenGridItem, xFactor: Float) {
|
||||||
if (item.id != draggedItem?.id) {
|
if (item.id != draggedItem?.id) {
|
||||||
|
@ -755,6 +736,20 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (abs(pageChangeSwipedPercentage) > 0f) {
|
||||||
|
gridItems.filter {
|
||||||
|
(it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT)
|
||||||
|
&& ((pageChangeSwipedPercentage > 0f && it.page == currentPage - 1) || (pageChangeSwipedPercentage < 0f && it.page == currentPage + 1))
|
||||||
|
&& !it.docked
|
||||||
|
}.forEach { item ->
|
||||||
|
if (item.outOfBounds()) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
handleItemDrawing(item, lastXFactor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isFirstDraw) {
|
if (isFirstDraw) {
|
||||||
gridItems.filter { it.type == ITEM_TYPE_WIDGET && !it.outOfBounds() }.forEach { item ->
|
gridItems.filter { it.type == ITEM_TYPE_WIDGET && !it.outOfBounds() }.forEach { item ->
|
||||||
bindWidget(item, true)
|
bindWidget(item, true)
|
||||||
|
@ -768,7 +763,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only draw page indicators when there is a need for it
|
// Only draw page indicators when there is a need for it
|
||||||
if (pageChangeAnimLeftPercentage > 0f || pageChangeIndicatorsAlpha != 0f) {
|
if (pageChangeAnimLeftPercentage > 0f || pageChangeIndicatorsAlpha != 0f || abs(pageChangeSwipedPercentage) > 0f) {
|
||||||
val pageCount = max(getMaxPage(), currentPage) + 1
|
val pageCount = max(getMaxPage(), currentPage) + 1
|
||||||
val pageIndicatorsRequiredWidth = pageCount * pageIndicatorRadius * 2 + pageCount * (pageIndicatorMargin - 1)
|
val pageIndicatorsRequiredWidth = pageCount * pageIndicatorRadius * 2 + pageCount * (pageIndicatorMargin - 1)
|
||||||
val usableWidth = getFakeWidth()
|
val usableWidth = getFakeWidth()
|
||||||
|
@ -789,8 +784,22 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
|
|
||||||
// Draw current page indicator on exact position
|
// Draw current page indicator on exact position
|
||||||
val currentIndicatorRangeStart = pageIndicatorsStart + lastPage * pageIndicatorStep
|
val currentIndicatorRangeStart = pageIndicatorsStart + lastPage * pageIndicatorStep
|
||||||
val currentIndicatorRangeEnd = pageIndicatorsStart + currentPage * pageIndicatorStep
|
val indicatorEndPage = if (abs(pageChangeSwipedPercentage) > 0f) {
|
||||||
val currentIndicatorPosition = MathUtils.lerp(currentIndicatorRangeStart, currentIndicatorRangeEnd, 1 - pageChangeAnimLeftPercentage)
|
if (pageChangeSwipedPercentage > 0f) {
|
||||||
|
currentPage - 1
|
||||||
|
} else {
|
||||||
|
currentPage + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentPage
|
||||||
|
}
|
||||||
|
val currentIndicatorRangeEnd = pageIndicatorsStart + indicatorEndPage * pageIndicatorStep
|
||||||
|
val lerpAmount = if (pageChangeAnimLeftPercentage > 0f) {
|
||||||
|
1 - pageChangeAnimLeftPercentage
|
||||||
|
} else {
|
||||||
|
abs(pageChangeSwipedPercentage)
|
||||||
|
}
|
||||||
|
val currentIndicatorPosition = MathUtils.lerp(currentIndicatorRangeStart, currentIndicatorRangeEnd, lerpAmount)
|
||||||
if (pageChangeIndicatorsAlpha != 0f) {
|
if (pageChangeIndicatorsAlpha != 0f) {
|
||||||
currentPageIndicatorPaint.alpha = (pageChangeIndicatorsAlpha * 255.0f).toInt()
|
currentPageIndicatorPaint.alpha = (pageChangeIndicatorsAlpha * 255.0f).toInt()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1087,11 +1096,13 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
private fun handlePageChange(redraw: Boolean = false) {
|
private fun handlePageChange(redraw: Boolean = false) {
|
||||||
pageChangeEnabled = false
|
pageChangeEnabled = false
|
||||||
pageChangeIndicatorsAlpha = 0f
|
pageChangeIndicatorsAlpha = 0f
|
||||||
|
val startingAt = 1 - abs(pageChangeSwipedPercentage)
|
||||||
|
pageChangeSwipedPercentage = 0f
|
||||||
removeCallbacks(startFadingIndicators)
|
removeCallbacks(startFadingIndicators)
|
||||||
if (redraw) {
|
if (redraw) {
|
||||||
redrawGrid()
|
redrawGrid()
|
||||||
}
|
}
|
||||||
ValueAnimator.ofFloat(1f, 0f)
|
ValueAnimator.ofFloat(startingAt, 0f)
|
||||||
.apply {
|
.apply {
|
||||||
addUpdateListener {
|
addUpdateListener {
|
||||||
pageChangeAnimLeftPercentage = it.animatedValue as Float
|
pageChangeAnimLeftPercentage = it.animatedValue as Float
|
||||||
|
@ -1112,6 +1123,63 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isBetweenPages() =
|
||||||
|
(pageChangeSwipedPercentage > 0f && pageChangeSwipedPercentage < 1f) || (pageChangeAnimLeftPercentage > 0f && pageChangeAnimLeftPercentage < 1f)
|
||||||
|
|
||||||
|
private fun getXFactorForCurrentPage(): Float {
|
||||||
|
return if (abs(pageChangeSwipedPercentage) > 0f) {
|
||||||
|
pageChangeSwipedPercentage
|
||||||
|
} else {
|
||||||
|
if (currentPage > lastPage) {
|
||||||
|
pageChangeAnimLeftPercentage
|
||||||
|
} else {
|
||||||
|
-pageChangeAnimLeftPercentage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getXFactorForLastPage(): Float {
|
||||||
|
return if (abs(pageChangeSwipedPercentage) > 0f) {
|
||||||
|
(1 - abs(pageChangeSwipedPercentage)) * -sign(pageChangeSwipedPercentage)
|
||||||
|
} else {
|
||||||
|
if (currentPage > lastPage) {
|
||||||
|
pageChangeAnimLeftPercentage - 1
|
||||||
|
} else {
|
||||||
|
1 - pageChangeAnimLeftPercentage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSwipeMovement(diffX: Float) {
|
||||||
|
if (!pageChangeEnabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPage < getMaxPage() && diffX > 0f || currentPage > 0 && diffX < 0f) {
|
||||||
|
pageChangeSwipedPercentage = (-diffX / width.toFloat()).coerceIn(-1f, 1f)
|
||||||
|
redrawGrid()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun finalizeSwipe() {
|
||||||
|
if (abs(pageChangeSwipedPercentage) > 0.5f) {
|
||||||
|
lastPage = currentPage
|
||||||
|
currentPage = if (pageChangeSwipedPercentage > 0f) {
|
||||||
|
currentPage - 1
|
||||||
|
} else {
|
||||||
|
currentPage + 1
|
||||||
|
}
|
||||||
|
handlePageChange(true)
|
||||||
|
} else {
|
||||||
|
lastPage = if (pageChangeSwipedPercentage > 0f) {
|
||||||
|
currentPage - 1
|
||||||
|
} else {
|
||||||
|
currentPage + 1
|
||||||
|
}
|
||||||
|
handlePageChange(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val PAGE_CHANGE_HOLD_THRESHOLD = 500L
|
private const val PAGE_CHANGE_HOLD_THRESHOLD = 500L
|
||||||
private const val PAGE_INDICATORS_FADE_DELAY = PAGE_CHANGE_HOLD_THRESHOLD + 300L
|
private const val PAGE_INDICATORS_FADE_DELAY = PAGE_CHANGE_HOLD_THRESHOLD + 300L
|
||||||
|
|
Loading…
Reference in New Issue