Commit b9d178c3 authored by Amit Kumar's avatar Amit Kumar 💻
Browse files

Recurse through open folder in all cases

parent d13159f2
Pipeline #151960 passed with stage
in 7 minutes and 57 seconds
...@@ -50,21 +50,11 @@ class Folder @JvmOverloads constructor( ...@@ -50,21 +50,11 @@ class Folder @JvmOverloads constructor(
attrs: AttributeSet? = null attrs: AttributeSet? = null
) : AbstractFloatingView(context, attrs), DragController.DragListener, ) : AbstractFloatingView(context, attrs), DragController.DragListener,
FolderTitleInput.OnBackKeyListener, FolderItem.FolderListener, View.OnFocusChangeListener, FolderTitleInput.OnBackKeyListener, FolderItem.FolderListener, View.OnFocusChangeListener,
OnEditorActionListener, DragSource { OnEditorActionListener, DragSource, DropTarget {
/** private var mScrollAreaOffset: Int = 0
* Fraction of icon width which behave as scroll region.
*/
private val ICON_OVERSCROLL_WIDTH_FACTOR = 0.45f
private val FOLDER_NAME_ANIMATION_DURATION = 633L
private val REORDER_DELAY = 250L
private val ON_EXIT_CLOSE_DELAY = 400L
private val sTempRect = Rect()
private val MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION = 10 private val MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION = 10
private val mReorderAlarm: Alarm = Alarm()
private val mOnExitAlarm: Alarm = Alarm() private val mOnExitAlarm: Alarm = Alarm()
val mItemsInReadingOrder = ArrayList<View>() val mItemsInReadingOrder = ArrayList<View>()
...@@ -79,8 +69,6 @@ class Folder @JvmOverloads constructor( ...@@ -79,8 +69,6 @@ class Folder @JvmOverloads constructor(
lateinit var mFolderTitleInput: FolderTitleInput lateinit var mFolderTitleInput: FolderTitleInput
private lateinit var mPageIndicator: CircleIndicator private lateinit var mPageIndicator: CircleIndicator
// Cell ranks used for drag and drop
var mTargetRank = 0
var mPrevTargetRank = 0 var mPrevTargetRank = 0
var mEmptyCellRank = 0 var mEmptyCellRank = 0
...@@ -138,7 +126,7 @@ class Folder @JvmOverloads constructor( ...@@ -138,7 +126,7 @@ class Folder @JvmOverloads constructor(
} }
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean { override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
ev?.let { /*ev?.let {
if (it.action == MotionEvent.ACTION_DOWN) { if (it.action == MotionEvent.ACTION_DOWN) {
val dl: DragLayer = launcher.dragLayer val dl: DragLayer = launcher.dragLayer
if (isEditingName()) { if (isEditingName()) {
...@@ -152,7 +140,7 @@ class Folder @JvmOverloads constructor( ...@@ -152,7 +140,7 @@ class Folder @JvmOverloads constructor(
return true return true
} }
} }
} }*/
return false return false
} }
...@@ -200,6 +188,7 @@ class Folder @JvmOverloads constructor( ...@@ -200,6 +188,7 @@ class Folder @JvmOverloads constructor(
private fun closeComplete(wasAnimated: Boolean) { private fun closeComplete(wasAnimated: Boolean) {
// TODO: Clear all active animations. // TODO: Clear all active animations.
(this.parent as DragLayer?)?.removeView(this) (this.parent as DragLayer?)?.removeView(this)
dragController?.removeDropTarget(this)
clearFocus() clearFocus()
folderIcon?.apply { folderIcon?.apply {
launcher.getLauncherPagedView().alpha = 1f launcher.getLauncherPagedView().alpha = 1f
...@@ -235,7 +224,7 @@ class Folder @JvmOverloads constructor( ...@@ -235,7 +224,7 @@ class Folder @JvmOverloads constructor(
// Convert to a string here to ensure that no other state associated with the text field // Convert to a string here to ensure that no other state associated with the text field
// gets saved. // gets saved.
val newTitle: String = mFolderTitleInput.text.toString() val newTitle: String = mFolderTitleInput.text.toString()
mInfo?.setTitle(newTitle) mInfo.setTitle(newTitle)
// Update database // Update database
launcher.getLauncherPagedView().updateDatabase() launcher.getLauncherPagedView().updateDatabase()
...@@ -253,14 +242,16 @@ class Folder @JvmOverloads constructor( ...@@ -253,14 +242,16 @@ class Folder @JvmOverloads constructor(
// we need to create the illusion that the item isn't added back to the folder yet, to // we need to create the illusion that the item isn't added back to the folder yet, to
// to correspond to the animation of the icon back into the folder. This is // to correspond to the animation of the icon back into the folder. This is
fun hideItem(info: LauncherItem) { fun hideItem(info: LauncherItem) {
getViewForInfo(info).apply { getViewForInfo(info)?.apply {
visibility = INVISIBLE this.clearAnimation()
this.visibility = INVISIBLE
} }
} }
fun showItem(info: LauncherItem) { fun showItem(info: LauncherItem) {
getViewForInfo(info)?.apply { getViewForInfo(info)?.apply {
visibility = VISIBLE this.clearAnimation()
this.visibility = VISIBLE
} }
} }
...@@ -271,6 +262,7 @@ class Folder @JvmOverloads constructor( ...@@ -271,6 +262,7 @@ class Folder @JvmOverloads constructor(
override fun onTitleChanged(title: CharSequence?) {} override fun onTitleChanged(title: CharSequence?) {}
override fun onRemove(item: LauncherItem) { override fun onRemove(item: LauncherItem) {
Log.d(TAG, "onRemove() called with: item = $item")
mItemsInvalidated = true mItemsInvalidated = true
val v: View? = getViewForInfo(item) val v: View? = getViewForInfo(item)
mContent.adapter?.notifyDataSetChanged() mContent.adapter?.notifyDataSetChanged()
...@@ -302,15 +294,12 @@ class Folder @JvmOverloads constructor( ...@@ -302,15 +294,12 @@ class Folder @JvmOverloads constructor(
if (dragObject.dragSource != this) { if (dragObject.dragSource != this) {
return return
} }
mCurrentDragView?.clearAnimation()
mContent.removeItem(mCurrentDragView) hideItem(dragObject.dragInfo)
if (dragObject.dragInfo is LauncherItem) { if (dragObject.dragInfo is LauncherItem) {
mItemsInvalidated = true mItemsInvalidated = true
SuppressInfoChanges().use { _ -> SuppressInfoChanges().use { _ ->
mInfo.remove( // mInfo?.remove(dragObject.dragInfo, true)
dragObject.dragInfo as LauncherItem,
true
)
} }
} }
mDragInProgress = true mDragInProgress = true
...@@ -400,8 +389,6 @@ class Folder @JvmOverloads constructor( ...@@ -400,8 +389,6 @@ class Folder @JvmOverloads constructor(
} }
}) })
// We use same size for height and width as we want to look it like square // We use same size for height and width as we want to look it like square
val height =
mDeviceProfile.cellHeightPx * 3 + resources.getDimensionPixelSize(R.dimen.folder_padding)
mContent.layoutParams?.width = mContent.layoutParams?.width =
mDeviceProfile.cellHeightPx * 3 + resources.getDimensionPixelSize(R.dimen.folder_padding) * 2 mDeviceProfile.cellHeightPx * 3 + resources.getDimensionPixelSize(R.dimen.folder_padding) * 2
mContent.layoutParams?.height = mContent.layoutParams?.height =
...@@ -480,6 +467,7 @@ class Folder @JvmOverloads constructor( ...@@ -480,6 +467,7 @@ class Folder @JvmOverloads constructor(
ViewGroup.LayoutParams.MATCH_PARENT ViewGroup.LayoutParams.MATCH_PARENT
) )
) )
dragController?.addDropTarget(this)
} else { } else {
Log.e( Log.e(
TAG, TAG,
...@@ -498,7 +486,6 @@ class Folder @JvmOverloads constructor( ...@@ -498,7 +486,6 @@ class Folder @JvmOverloads constructor(
// dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice. // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice.
mDeleteFolderOnDropCompleted = false mDeleteFolderOnDropCompleted = false
// centerAboutIcon() // centerAboutIcon()
Log.i(TAG, "animateOpen: " + mContent.getItemCount() + " " + mInfo.items.size)
val anim: AnimatorSet = FolderAnimationManager(this, true /* isOpening */).animator val anim: AnimatorSet = FolderAnimationManager(this, true /* isOpening */).animator
anim.play(ObjectAnimator.ofFloat(launcher.getLauncherPagedView(), View.ALPHA, 0f)) anim.play(ObjectAnimator.ofFloat(launcher.getLauncherPagedView(), View.ALPHA, 0f))
.with(ObjectAnimator.ofFloat(launcher.hotseat, View.ALPHA, 0f)) .with(ObjectAnimator.ofFloat(launcher.hotseat, View.ALPHA, 0f))
...@@ -518,6 +505,7 @@ class Folder @JvmOverloads constructor( ...@@ -518,6 +505,7 @@ class Folder @JvmOverloads constructor(
launcher.getLauncherPagedView().alpha = 0f launcher.getLauncherPagedView().alpha = 0f
launcher.hotseat.alpha = 0f launcher.hotseat.alpha = 0f
launcher.getLauncherPagedView().pageIndicator.alpha = 0f launcher.getLauncherPagedView().pageIndicator.alpha = 0f
mContent.setFocusOnFirstChild()
} }
override fun onAnimationCancel(animation: Animator?) { override fun onAnimationCancel(animation: Animator?) {
...@@ -535,14 +523,18 @@ class Folder @JvmOverloads constructor( ...@@ -535,14 +523,18 @@ class Folder @JvmOverloads constructor(
} }
fun completeDragExit() { fun completeDragExit() {
if (mIsOpen) { when {
close(true) mIsOpen -> {
mRearrangeOnClose = true close(true)
} else if (mState == STATE_ANIMATING) { mRearrangeOnClose = true
mRearrangeOnClose = true }
} else { mState == STATE_ANIMATING -> {
rearrangeChildren() mRearrangeOnClose = true
clearDragInfo() }
else -> {
rearrangeChildren()
clearDragInfo()
}
} }
} }
...@@ -563,7 +555,7 @@ class Folder @JvmOverloads constructor( ...@@ -563,7 +555,7 @@ class Folder @JvmOverloads constructor(
* @param itemCount if greater than the total children count, empty spaces are left at the end, * @param itemCount if greater than the total children count, empty spaces are left at the end,
* otherwise it is ignored. * otherwise it is ignored.
*/ */
fun rearrangeChildren(itemCount: Int) { private fun rearrangeChildren(itemCount: Int) {
mContent.adapter?.notifyDataSetChanged() mContent.adapter?.notifyDataSetChanged()
mItemsInvalidated = true mItemsInvalidated = true
} }
...@@ -648,7 +640,12 @@ class Folder @JvmOverloads constructor( ...@@ -648,7 +640,12 @@ class Folder @JvmOverloads constructor(
} }
} else { } else {
// The drag failed, we need to return the item to the folder // The drag failed, we need to return the item to the folder
mContent.adapter?.notifyDataSetChanged() mContent.adapter =
FolderPagerAdapter(context, mInfo.items, launcher.deviceProfile)
launcher.dragLayer.removeView(d?.dragView)
d?.dragView = null
invalidate()
launcher.getLauncherPagedView().wobbleLayouts()
} }
mDeleteFolderOnDropCompleted = false mDeleteFolderOnDropCompleted = false
...@@ -656,7 +653,7 @@ class Folder @JvmOverloads constructor( ...@@ -656,7 +653,7 @@ class Folder @JvmOverloads constructor(
mItemAddedBackToSelfViaIcon = false mItemAddedBackToSelfViaIcon = false
mCurrentDragView = null mCurrentDragView = null
// Reordering may have occured, and we need to save the new item locations. We do this once // Reordering may have occurred, and we need to save the new item locations. We do this once
// at the end to prevent unnecessary database operations. // at the end to prevent unnecessary database operations.
launcher.getLauncherPagedView().updateDatabase() launcher.getLauncherPagedView().updateDatabase()
} }
...@@ -697,6 +694,8 @@ class Folder @JvmOverloads constructor( ...@@ -697,6 +694,8 @@ class Folder @JvmOverloads constructor(
const val STATE_ANIMATING = 1 const val STATE_ANIMATING = 1
const val STATE_OPEN = 2 const val STATE_OPEN = 2
private const val ON_EXIT_CLOSE_DELAY = 400L
const val TAG = "Folder" const val TAG = "Folder"
private var sDefaultFolderName: String? = null private var sDefaultFolderName: String? = null
...@@ -740,4 +739,51 @@ class Folder @JvmOverloads constructor( ...@@ -740,4 +739,51 @@ class Folder @JvmOverloads constructor(
mInfo.removeListener(this@Folder) mInfo.removeListener(this@Folder)
} }
} }
override fun isDropEnabled(): Boolean = mState != STATE_ANIMATING
override fun onDrop(dragObject: DropTarget.DragObject?, options: DragOptions?) {
// Do nothing here as we don't allow to drop icon in folder.
}
override fun onDragEnter(d: DropTarget.DragObject) {
mPrevTargetRank = -1
mOnExitAlarm.cancelAlarm()
// Get the area offset such that the folder only closes if half the drag icon width
// is outside the folder area
// Get the area offset such that the folder only closes if half the drag icon width
// is outside the folder area
mScrollAreaOffset = d.dragView.dragRegionWidth / 2 - d.xOffset
}
override fun onDragOver(dragObject: DropTarget.DragObject?) {
// Do Nothing here, we don't allow drop.
Log.d(TAG, "onDragOver() called with: dragObject = $dragObject")
}
override fun onDragExit(d: DropTarget.DragObject) {
// We only close the folder if this is a true drag exit, ie. not because
// a drop has occurred above the folder.
if (!d.dragComplete) {
mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener)
mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY)
}
}
override fun acceptDrop(dragObject: DropTarget.DragObject?): Boolean = false
override fun prepareAccessibilityDrop() {
}
override fun getHitRectRelativeToDragLayer(outRect: Rect?) {
launcher.dragLayer.getDescendantRectRelativeToSelf(mContent, outRect)
// mContent.getHitRect(outRect)
/*outRect!!.left -= mScrollAreaOffset
outRect!!.right += mScrollAreaOffset*/
Log.i(TAG, "getHitRectRelativeToDragLayer: " + outRect)
}
fun getContent(): ViewGroup {
return mContent
}
} }
...@@ -202,6 +202,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -202,6 +202,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
*/ */
public final Map<ShortcutKey, MutableInt> pinnedShortcutCounts = new HashMap<>(); public final Map<ShortcutKey, MutableInt> pinnedShortcutCounts = new HashMap<>();
/** The value that {@link #mTransitionProgress} must be greater than for
* {@link #transitionStateShouldAllowDrop()} to return true. */
private static final float ALLOW_DROP_TRANSITION_PROGRESS = 0.25f;
public LauncherPagedView(Context context, AttributeSet attributeSet) { public LauncherPagedView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0); this(context, attributeSet, 0);
} }
...@@ -333,7 +337,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -333,7 +337,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
LauncherItem launcherItem = launcherItems.get(i); LauncherItem launcherItem = launcherItems.get(i);
View appView; View appView;
if (launcherItem.itemType == Constants.ITEM_TYPE_FOLDER) { if (launcherItem.itemType == Constants.ITEM_TYPE_FOLDER) {
FolderIcon folderIcon = FolderIcon.Companion.fromXml(R.layout.folder_icon, FolderIcon folderIcon = FolderIcon.Companion.fromXml(
R.layout.folder_icon,
getScreenWithId(launcherItem.screenId), getScreenWithId(launcherItem.screenId),
(FolderItem) launcherItem (FolderItem) launcherItem
); );
...@@ -1379,11 +1384,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -1379,11 +1384,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
if (!workspaceInModalState() && !mIsSwitchingState) { if (!workspaceInModalState() && !mIsSwitchingState) {
result = super.scrollLeft(); result = super.scrollLeft();
} }
// TODO: Fix this asap Folder openFolder = Folder.Companion.getOpen(mLauncher);
/*Folder openFolder = Folder.getOpen(mLauncher);
if (openFolder != null) { if (openFolder != null) {
openFolder.completeDragExit(); openFolder.completeDragExit();
}*/ }
return result; return result;
} }
...@@ -1393,11 +1397,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -1393,11 +1397,10 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
if (!workspaceInModalState() && !mIsSwitchingState) { if (!workspaceInModalState() && !mIsSwitchingState) {
result = super.scrollRight(); result = super.scrollRight();
} }
// TODO: Fix this asap Folder openFolder = Folder.Companion.getOpen(mLauncher);
/*Folder openFolder = Folder.getOpen(mLauncher);
if (openFolder != null) { if (openFolder != null) {
openFolder.completeDragExit(); openFolder.completeDragExit();
}*/ }
return result; return result;
} }
...@@ -1687,7 +1690,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -1687,7 +1690,8 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
final int[] touchXY = new int[]{(int) mDragViewVisualCenter[0], final int[] touchXY = new int[]{(int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1]}; (int) mDragViewVisualCenter[1]};
// onDropExternal(touchXY, dropTargetLayout, d); // onDropExternal(touchXY, dropTargetLayout, d);
} else { }
else {
final View cell = mDragInfo.getCell(); final View cell = mDragInfo.getCell();
boolean droppedOnOriginalCellDuringTransition = false; boolean droppedOnOriginalCellDuringTransition = false;
Runnable onCompleteRunnable = null; Runnable onCompleteRunnable = null;
...@@ -2211,7 +2215,7 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -2211,7 +2215,7 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
} }
// Handle the drag over // Handle the drag over
if (mDragTargetLayout != null) { if (mDragTargetLayout != null && child != null) {
// We want the point to be mapped to the dragTarget. // We want the point to be mapped to the dragTarget.
if (mLauncher.isHotseatLayout(mDragTargetLayout)) { if (mLauncher.isHotseatLayout(mDragTargetLayout)) {
mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter); mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
...@@ -2301,8 +2305,46 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -2301,8 +2305,46 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
} }
@Override @Override
public boolean acceptDrop(DragObject dragObject) { public boolean acceptDrop(DragObject d) {
CellLayout dropTargetLayout = mDropToLayout; CellLayout dropTargetLayout = mDropToLayout;
if(d.dragSource != this) {
if (dropTargetLayout == null) {
return false;
}
if (!transitionStateShouldAllowDrop()) return false;
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], dropTargetLayout,
mTargetCell);
float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
mDragViewVisualCenter[1], mTargetCell);
if (mCreateUserFolderOnDrop && willCreateUserFolder(d.dragInfo,
dropTargetLayout, mTargetCell, distance, true)) {
return true;
}
if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder(d.dragInfo,
dropTargetLayout, mTargetCell, distance)) {
return true;
}
int[] resultSpan = new int[2];
mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], 1, 1, 1, 1,
null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);
boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
// Don't accept the drop if there's no room for the item
if (!foundCell) {
onNoCellFound(dropTargetLayout);
return false;
}
}
long screenId = getIdForScreen(dropTargetLayout); long screenId = getIdForScreen(dropTargetLayout);
if (screenId == EXTRA_EMPTY_SCREEN_ID) { if (screenId == EXTRA_EMPTY_SCREEN_ID) {
commitExtraEmptyScreen(); commitExtraEmptyScreen();
...@@ -2310,6 +2352,25 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -2310,6 +2352,25 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
return true; return true;
} }
/**
* Updates the point in {@param xy} to point to the co-ordinate space of {@param layout}
* @param layout either hotseat of a page in workspace
* @param xy the point location in workspace co-ordinate space
*/
private void mapPointFromDropLayout(CellLayout layout, float[] xy) {
if (mLauncher.isHotseatLayout(layout)) {
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, xy, true);
mLauncher.getDragLayer().mapCoordInSelfToDescendant(layout, xy);
} else {
mapPointFromSelfToChild(layout, xy);
}
}
private boolean transitionStateShouldAllowDrop() {
return (!isSwitchingState() || mTransitionProgress > ALLOW_DROP_TRANSITION_PROGRESS) &&
workspaceIconsCanBeDragged();
}
@Override @Override
public void prepareAccessibilityDrop() { public void prepareAccessibilityDrop() {
Log.d(TAG, "prepareAccessibilityDrop() called"); Log.d(TAG, "prepareAccessibilityDrop() called");
...@@ -2651,9 +2712,18 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V ...@@ -2651,9 +2712,18 @@ public class LauncherPagedView extends PagedView<PageIndicatorDots> implements V
return; return;
} }
} }
Folder folder = Folder.Companion.getOpen(mLauncher);
if (folder != null && !folder.isDestroyed()) {
for (int i = 0; i < folder.getContent().getChildCount(); i++) {
GridLayout grid = (GridLayout) folder.getContent().getChildAt(i);
if (mapOverCellLayout(recurse, grid, op)) {
return;
}
}
}
} }
private boolean mapOverCellLayout(boolean recurse, CellLayout layout, ItemOperator op) { private boolean mapOverCellLayout(boolean recurse, GridLayout layout, ItemOperator op) {
// TODO(b/128460496) Potential race condition where layout is not yet loaded // TODO(b/128460496) Potential race condition where layout is not yet loaded
if (layout == null) { if (layout == null) {
return false; return false;
......
...@@ -3,6 +3,7 @@ package foundation.e.blisslauncher.features.folder ...@@ -3,6 +3,7 @@ package foundation.e.blisslauncher.features.folder
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.GridLayout import android.widget.GridLayout
import androidx.core.view.get import androidx.core.view.get
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
...@@ -67,4 +68,11 @@ class FolderViewPager @JvmOverloads constructor( ...@@ -67,4 +68,11 @@ class FolderViewPager @JvmOverloads constructor(
(getChildAt(lastPageIndex) as GridLayout).childCount + lastPageIndex * 9 // maxItems per page (getChildAt(lastPageIndex) as GridLayout).childCount + lastPageIndex * 9 // maxItems per page
} }
} }