diff options
5 files changed, 74 insertions, 210 deletions
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 4d3eb5e98..f9dc796fd 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -3824,7 +3824,7 @@ public class Workspace extends PagedView ItemInfo info = (ItemInfo) item.getTag(); if (recurse && info instanceof FolderInfo && item instanceof FolderIcon) { FolderIcon folder = (FolderIcon) item; - ArrayList<View> folderChildren = folder.getFolder().getItemsInRankOrder(); + ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder(); // map over all the children in the folder final int childCount = folderChildren.size(); for (int childIdx = 0; childIdx < childCount; childIdx++) { diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java index 6cd086b38..34335330b 100644 --- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java @@ -369,7 +369,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme Folder folder = Folder.getOpen(mLauncher); if (folder != null) { - if (!folder.getItemsInRankOrder().contains(item)) { + if (!folder.getItemsInReadingOrder().contains(item)) { folder.close(true); folder = null; } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 3184d6d43..622cd1096 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -133,7 +133,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC private final Alarm mOnScrollHintAlarm = new Alarm(); @Thunk final Alarm mScrollPauseAlarm = new Alarm(); - @Thunk final ArrayList<View> mItemsInRankOrder = new ArrayList<>(); + @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); private AnimatorSet mCurrentAnimator; @@ -284,7 +284,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC if (tag instanceof ShortcutInfo) { ShortcutInfo item = (ShortcutInfo) tag; - mEmptyCellRank = mContent.getReadingOrderPosForRank(item.rank); + mEmptyCellRank = item.rank; mCurrentDragView = v; mDragController.addDragListener(this); @@ -705,7 +705,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } public void beginExternalDrag() { - mEmptyCellRank = mContent.getReadingOrderPosForRank(mContent.allocateRankForNewItem()); + mEmptyCellRank = mContent.allocateRankForNewItem(); mIsExternalDrag = true; mDragInProgress = true; @@ -1000,7 +1000,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC ShortcutInfo info = (ShortcutInfo) d.dragInfo; View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info) ? mCurrentDragView : mContent.createNewView(info); - ArrayList<View> views = getItemsInRankOrder(); + ArrayList<View> views = getItemsInReadingOrder(); views.add(info.rank, icon); mContent.arrangeChildren(views, views.size()); mItemsInvalidated = true; @@ -1075,7 +1075,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } private void updateItemLocationsInDatabaseBatch() { - ArrayList<View> list = getItemsInRankOrder(); + ArrayList<View> list = getItemsInReadingOrder(); ArrayList<ItemInfo> items = new ArrayList<ItemInfo>(); for (int i = 0; i < list.size(); i++) { View v = list.get(i); @@ -1234,7 +1234,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC * otherwise it is ignored. */ public void rearrangeChildren(int itemCount) { - ArrayList<View> views = getItemsInRankOrder(); + ArrayList<View> views = getItemsInReadingOrder(); mContent.arrangeChildren(views, Math.max(itemCount, views.size())); mItemsInvalidated = true; } @@ -1379,19 +1379,23 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC View currentDragView; if (mIsExternalDrag) { + currentDragView = mContent.createAndAddViewForRank(si, mEmptyCellRank); + // Actually move the item in the database if it was an external drag. Call this // before creating the view, so that ShortcutInfo is updated appropriately. - mLauncher.getModelWriter().addOrMoveItemInDatabase(si, mInfo.id, 0, si.cellX, si.cellY); - } + mLauncher.getModelWriter().addOrMoveItemInDatabase( + si, mInfo.id, 0, si.cellX, si.cellY); - currentDragView = mIsExternalDrag - ? mContent.createNewView(si) - : mCurrentDragView; - mIsExternalDrag = false; - - // Note: addViewForRankDuringDragAndDrop handles rearranging the children. - mContent.addViewForRankDuringDragAndDrop(currentDragView, si, mEmptyCellRank); - mItemsInvalidated = true; + // We only need to update the locations if it doesn't get handled in + // #onDropCompleted. + if (d.dragSource != this) { + updateItemLocationsInDatabaseBatch(); + } + mIsExternalDrag = false; + } else { + currentDragView = mCurrentDragView; + mContent.addViewForRank(currentDragView, si, mEmptyCellRank); + } if (d.dragView.hasDrawn()) { // Temporarily reset the scale such that the animation target gets calculated @@ -1409,6 +1413,9 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC currentDragView.setVisibility(VISIBLE); } + mItemsInvalidated = true; + rearrangeChildren(); + // Temporarily suppress the listener, as we did all the work already here. try (SuppressInfoChanges s = new SuppressInfoChanges()) { mInfo.add(si, false); @@ -1446,7 +1453,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC mLauncher.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0, item.cellX, item.cellY); - ArrayList<View> items = new ArrayList<>(getItemsInRankOrder()); + ArrayList<View> items = new ArrayList<>(getItemsInReadingOrder()); items.add(rank, view); mContent.arrangeChildren(items, items.size()); mItemsInvalidated = true; @@ -1493,34 +1500,24 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC public void onTitleChanged(CharSequence title) { } - public ArrayList<View> getItemsInRankOrder() { + public ArrayList<View> getItemsInReadingOrder() { if (mItemsInvalidated) { - mItemsInRankOrder.clear(); - mItemsInRankOrder.addAll(getItemsInReadingOrder()); - mItemsInRankOrder.sort(VIEW_RANK_COMPARATOR); + mItemsInReadingOrder.clear(); + mContent.iterateOverItems(new ItemOperator() { + @Override + public boolean evaluate(ItemInfo info, View view) { + mItemsInReadingOrder.add(view); + return false; + } + }); mItemsInvalidated = false; } - return mItemsInRankOrder; - } - - /** - * This is an expensive call. Consider using {@link #getItemsInRankOrder()} instead. - */ - public ArrayList<View> getItemsInReadingOrder() { - final ArrayList<View> itemsInReadingOrder = new ArrayList<>(); - mContent.iterateOverItems(new ItemOperator() { - @Override - public boolean evaluate(ItemInfo info, View view) { - itemsInReadingOrder.add(view); - return false; - } - }); - return itemsInReadingOrder; + return mItemsInReadingOrder; } public List<BubbleTextView> getItemsOnPage(int page) { - ArrayList<View> allItems = getItemsInRankOrder(); + ArrayList<View> allItems = getItemsInReadingOrder(); int lastPage = mContent.getPageCount() - 1; int totalItemsInFolder = allItems.size(); int itemsPerPage = mContent.itemsPerPage(); @@ -1627,13 +1624,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } }; - public static final Comparator<View> VIEW_RANK_COMPARATOR = new Comparator<View>() { - @Override - public int compare(View lhs, View rhs) { - return ITEM_POS_COMPARATOR.compare((ItemInfo) lhs.getTag(), (ItemInfo) rhs.getTag()); - } - }; - /** * Temporary resource held while we don't want to handle info changes */ diff --git a/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java b/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java index eb415b945..11c10783c 100644 --- a/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java +++ b/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java @@ -31,6 +31,7 @@ public class FolderIconPreviewVerifier { private final int[] mGridSize = new int[2]; private int mGridCountX; + private boolean mDisplayingUpperLeftQuadrant = false; public FolderIconPreviewVerifier(InvariantDeviceProfile profile) { mMaxGridCountX = profile.numFolderColumns; @@ -42,6 +43,16 @@ public class FolderIconPreviewVerifier { FolderPagedView.calculateGridSize(info.contents.size(), 0, 0, mMaxGridCountX, mMaxGridCountY, mMaxItemsPerPage, mGridSize); mGridCountX = mGridSize[0]; + int numItemsInFolder = info.contents.size(); + mDisplayingUpperLeftQuadrant = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION + && !FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON + && numItemsInFolder > FolderIcon.NUM_ITEMS_IN_PREVIEW; + + if (mDisplayingUpperLeftQuadrant) { + FolderPagedView.calculateGridSize(info.contents.size(), 0, 0, mMaxGridCountX, + mMaxGridCountY, mMaxItemsPerPage, mGridSize); + mGridCountX = mGridSize[0]; + } } /** @@ -57,9 +68,9 @@ public class FolderIconPreviewVerifier { * @return True iff the icon is in the 2x2 upper left quadrant of the Folder. */ public boolean isItemInPreview(int page, int rank) { - if (page > 0) { - // First page items are laid out such that the first 4 items are always in the upper - // left quadrant. For all other pages, we need to check the row and col. + // First page items are laid out such that the first 4 items are always in the upper + // left quadrant. For all other pages, we need to check the row and col. + if (page > 0 || mDisplayingUpperLeftQuadrant) { int col = rank % mGridCountX; int row = rank / mGridCountX; return col < 2 && row < 2; diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 9bf20feaf..f4ac0a140 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -201,29 +201,18 @@ public class FolderPagedView extends PagedView { } public void allocateSpaceForRank(int rank) { - ArrayList<View> views = new ArrayList<>(mFolder.getItemsInRankOrder()); + ArrayList<View> views = new ArrayList<>(mFolder.getItemsInReadingOrder()); views.add(rank, null); arrangeChildren(views, views.size(), false); } - private ArrayList<View> createListWithViewAtPos(ArrayList<View> list, View v, int position) { - ArrayList<View> newList = new ArrayList<>(list.size() + 1); - newList.addAll(list); - newList.add(position, v); - return newList; - } - /** - * Create space for a new item and returns the rank for that item. + * Create space for a new item at the end, and returns the rank for that item. * Also sets the current page to the last page. */ public int allocateRankForNewItem() { - ArrayList<View> rankOrder = mFolder.getItemsInRankOrder(); - int rank = rankOrder.size(); - - ArrayList<View> views = createListWithViewAtPos(rankOrder, null, rank); - arrangeChildren(views, views.size(), false); - + int rank = getItemCount(); + allocateSpaceForRank(rank); setCurrentPage(rank / mMaxItemsPerPage); return rank; } @@ -240,59 +229,20 @@ public class FolderPagedView extends PagedView { * related attributes. It assumes that {@param item} is already attached to the view. */ public void addViewForRank(View view, ShortcutInfo item, int rank) { - updateShortcutInfoWithRank(item, rank); - - ArrayList<View> views = createListWithViewAtPos(mFolder.getItemsInRankOrder(), view, rank); - arrangeChildren(views, views.size(), false); - } + int pagePos = rank % mMaxItemsPerPage; + int pageNo = rank / mMaxItemsPerPage; - /** - * Similar to {@link #addViewForRank(View, ShortcutInfo, int)}}, but specific to real time - * reorder. - * - * The difference here is that during real time reorder, we are moving the Views in a contained - * order. - */ - public void addViewForRankDuringReorder(View view, ShortcutInfo item, int rank) { - updateShortcutInfoWithRank(item, rank); + item.rank = rank; + item.cellX = pagePos % mGridCountX; + item.cellY = pagePos / mGridCountX; CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); lp.cellX = item.cellX; lp.cellY = item.cellY; - - int pageNo = rank / mMaxItemsPerPage; getPageAt(pageNo).addViewToCellLayout( view, -1, mFolder.mLauncher.getViewIdForItem(item), lp, true); } - /** - * Similar to {@link #addViewForRank(View, ShortcutInfo, int)}, but specific to drag and drop. - * - * The difference is that we handle the drag and drop by adjusting the reading order of the - * children, rather than based on their rank. - */ - public void addViewForRankDuringDragAndDrop(View view, ShortcutInfo item, int readingRank) { - updateShortcutInfoWithRank(item, readingRank); - - ArrayList<View> views = createListWithViewAtPos(mFolder.getItemsInReadingOrder(), view, - readingRank); - - int numItems = views.size(); - ArrayList<View> rankOrder = new ArrayList<>(numItems); - for (int i = 0; i < numItems; ++i) { - rankOrder.add(views.get(getReadingOrderPosForRank(i))); - } - - arrangeChildren(rankOrder, numItems, false); - } - - private void updateShortcutInfoWithRank(ShortcutInfo info, int rank) { - info.rank = rank; - getCellXYPositionForRank(rank, sTmpArray); - info.cellX = sTmpArray[0]; - info.cellY = sTmpArray[1]; - } - @SuppressLint("InflateParams") public View createNewView(ShortcutInfo item) { final BubbleTextView textView = (BubbleTextView) mInflater.inflate( @@ -360,19 +310,18 @@ public class FolderPagedView extends PagedView { * It essentially removes all views from all the pages and then adds them again in appropriate * page. * - * @param rankOrderedList the rank-ordered list of children. + * @param list the ordered list of children. * @param itemCount if greater than the total children count, empty spaces are left * at the end, otherwise it is ignored. * */ - public void arrangeChildren(ArrayList<View> rankOrderedList, int itemCount) { - arrangeChildren(rankOrderedList, itemCount, true); + public void arrangeChildren(ArrayList<View> list, int itemCount) { + arrangeChildren(list, itemCount, true); } @SuppressLint("RtlHardcoded") - private void arrangeChildren(ArrayList<View> rankOrderedList, int itemCount, - boolean saveChanges) { - ArrayList<CellLayout> pages = new ArrayList<CellLayout>(); + private void arrangeChildren(ArrayList<View> list, int itemCount, boolean saveChanges) { + ArrayList<CellLayout> pages = new ArrayList<>(); for (int i = 0; i < getChildCount(); i++) { CellLayout page = (CellLayout) getChildAt(i); page.removeAllViews(); @@ -390,7 +339,7 @@ public class FolderPagedView extends PagedView { Launcher.getLauncher(getContext()).getDeviceProfile().inv); rank = 0; for (int i = 0; i < itemCount; i++) { - View v = rankOrderedList.size() > i ? rankOrderedList.get(i) : null; + View v = list.size() > i ? list.get(i) : null; if (currentPage == null || position >= mMaxItemsPerPage) { // Next page if (pageItr.hasNext()) { @@ -403,10 +352,8 @@ public class FolderPagedView extends PagedView { if (v != null) { CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); - getCellXYPositionForRank(rank, sTmpArray); - newX = sTmpArray[0]; - newY = sTmpArray[1]; - + newX = position % mGridCountX; + newY = position / mGridCountX; ItemInfo info = (ItemInfo) v.getTag(); if (info.cellX != newX || info.cellY != newY || info.rank != rank) { info.cellX = newX; @@ -704,7 +651,7 @@ public class FolderPagedView extends PagedView { if (v != null) { if (pageToAnimate != p) { page.removeView(v); - addViewForRankDuringReorder(v, (ShortcutInfo) v.getTag(), moveStart); + addViewForRank(v, (ShortcutInfo) v.getTag(), moveStart); } else { // Do a fake animation before removing it. final int newRank = moveStart; @@ -717,14 +664,14 @@ public class FolderPagedView extends PagedView { mPendingAnimations.remove(v); v.setTranslationX(oldTranslateX); ((CellLayout) v.getParent().getParent()).removeView(v); - addViewForRankDuringReorder(v, (ShortcutInfo) v.getTag(), newRank); + addViewForRank(v, (ShortcutInfo) v.getTag(), newRank); } }; v.animate() - .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth()) - .setDuration(REORDER_ANIMATION_DURATION) - .setStartDelay(0) - .withEndAction(endAction); + .translationXBy((direction > 0 ^ mIsRtl) ? -v.getWidth() : v.getWidth()) + .setDuration(REORDER_ANIMATION_DURATION) + .setStartDelay(0) + .withEndAction(endAction); mPendingAnimations.put(v, endAction); } } @@ -754,88 +701,4 @@ public class FolderPagedView extends PagedView { public int itemsPerPage() { return mMaxItemsPerPage; } - - /** - * Returns the reading order position for a given rank. - * - * ie. For the permutation below, rank 0 returns 0, rank 1 returns 1, rank 4 returns 2, - * rank 2 returns 3, rank 3 returns 4, rank 5 returns 5. - * - * R0 R1 R4 - * R2 R3 R5 - */ - public int getReadingOrderPosForRank(int rank) { - if (rank >= mMaxItemsPerPage) { - return rank; - } - - getCellXYPositionForRank(rank, sTmpArray); - return sTmpArray[0] + (mGridCountX * sTmpArray[1]); - } - - /** - * Returns the cell XY position for a Folder item with the given rank. - */ - public void getCellXYPositionForRank(int rank, int[] outXY) { - boolean onFirstPage = rank < mMaxItemsPerPage; - - if (onFirstPage && mGridCountX == 3) { - outXY[0] = FolderPermutation.THREE_COLS[rank][0]; - outXY[1] = FolderPermutation.THREE_COLS[rank][1]; - } else if (onFirstPage && mGridCountX == 4) { - outXY[0] = FolderPermutation.FOUR_COLS[rank][0]; - outXY[1] = FolderPermutation.FOUR_COLS[rank][1]; - } else if (onFirstPage && mGridCountX == 5) { - outXY[0] = FolderPermutation.FIVE_COLS[rank][0]; - outXY[1] = FolderPermutation.FIVE_COLS[rank][1]; - } else { - outXY[0] = (rank % mMaxItemsPerPage) % mGridCountX; - outXY[1] = (rank % mMaxItemsPerPage) / mGridCountX; - } - } - - /** - * Provides the mapping between a folder item's rank and its cell location, based on the - * number of columns. - * - * We use this mapping, rather than the regular reading order, to preserve the items in the - * upper left quadrant of the Folder. This allows a smooth transition between the FolderIcon - * and the opened Folder. - * - * TODO: We will replace these hard coded tables with an algorithm b/62986680 - */ - private static class FolderPermutation { - /** - * R0 R1 R4 - * R2 R3 R5 - * R6 R7 R8 - */ - static final int[][] THREE_COLS = new int[][] { - {0, 0}, {1, 0}, {0, 1}, {1, 1}, {2, 0}, {2, 1}, {0, 2}, {1, 2}, {2, 2} - }; - - /** - * R0 R1 R4 R6 - * R2 R3 R5 R7 - * R8 R9 R10 R11 - * R12 R13 R14 R15 - */ - static final int[][] FOUR_COLS = new int[][] { - {0, 0}, {1, 0}, {0, 1}, {1, 1}, {2, 0}, {2, 1}, {3, 0}, {3, 1}, {0, 2}, {1, 2}, - {2, 2}, {3, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3} - }; - - /** - * R0 R1 R4 R6 R12 - * R2 R3 R5 R7 R13 - * R8 R9 R10 R11 R14 - * R15 R16 R17 R18 R19 - * R20 R21 R22 R23 R24 - */ - static final int[][] FIVE_COLS = new int[][] { - {0, 0}, {1, 0}, {0, 1}, {1, 1}, {2, 0}, {2, 1}, {3, 0}, {3, 1}, {0, 2}, {1, 2}, - {2, 2}, {3, 2}, {4, 0}, {4, 1}, {4, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, - {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4} - }; - } } |