diff options
Diffstat (limited to 'src/com/android/launcher3/celllayout/ReorderAlgorithm.java')
-rw-r--r-- | src/com/android/launcher3/celllayout/ReorderAlgorithm.java | 165 |
1 files changed, 91 insertions, 74 deletions
diff --git a/src/com/android/launcher3/celllayout/ReorderAlgorithm.java b/src/com/android/launcher3/celllayout/ReorderAlgorithm.java index 8754b748e0..4ecc90004d 100644 --- a/src/com/android/launcher3/celllayout/ReorderAlgorithm.java +++ b/src/com/android/launcher3/celllayout/ReorderAlgorithm.java @@ -45,28 +45,36 @@ public class ReorderAlgorithm { * This method differs from closestEmptySpaceReorder and dropInPlaceSolution because this method * will move items around and will change the shape of the item if possible to try to find a * solution. - * <p> + * * When changing the size of the widget this method will try first subtracting -1 in the x * dimension and then subtracting -1 in the y dimension until finding a possible solution or * until it no longer can reduce the span. * - * @param decX whether it will decrease the horizontal or vertical span if it can't find a - * solution for the current span. + * @param pixelX X coordinate in pixels in the screen + * @param pixelY Y coordinate in pixels in the screen + * @param minSpanX minimum possible horizontal span it will try to find a solution for. + * @param minSpanY minimum possible vertical span it will try to find a solution for. + * @param spanX horizontal cell span + * @param spanY vertical cell span + * @param direction direction in which it will try to push the items intersecting the desired + * view + * @param dragView view being dragged in reorder + * @param decX whether it will decrease the horizontal or vertical span if it can't find a + * solution for the current span. + * @param solution variable to store the solution * @return the same solution variable */ - public ItemConfiguration findReorderSolution(ReorderParameters reorderParameters, - boolean decX) { - return findReorderSolutionRecursive(reorderParameters.getPixelX(), - reorderParameters.getPixelY(), reorderParameters.getMinSpanX(), - reorderParameters.getMinSpanY(), reorderParameters.getSpanX(), - reorderParameters.getSpanY(), mCellLayout.mDirectionVector, - reorderParameters.getDragView(), decX, reorderParameters.getSolution()); + public ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, + int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX, + ItemConfiguration solution) { + return findReorderSolutionRecursive(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, + direction, dragView, decX, solution); } - private ItemConfiguration findReorderSolutionRecursive(int pixelX, int pixelY, int minSpanX, - int minSpanY, int spanX, int spanY, int[] direction, View dragView, boolean decX, - ItemConfiguration solution) { + private ItemConfiguration findReorderSolutionRecursive(int pixelX, int pixelY, + int minSpanX, int minSpanY, int spanX, int spanY, int[] direction, View dragView, + boolean decX, ItemConfiguration solution) { // Copy the current state into the solution. This solution will be manipulated as necessary. mCellLayout.copyCurrentStateToSolution(solution); // Copy the current occupied array into the temporary occupied array. This array will be @@ -81,8 +89,8 @@ public class ReorderAlgorithm { boolean success; // First we try the exact nearest position of the item being dragged, // we will then want to try to move this around to other neighbouring positions - success = rearrangementExists(result[0], result[1], spanX, spanY, direction, dragView, - solution); + success = rearrangementExists(result[0], result[1], spanX, spanY, direction, + dragView, solution); if (!success) { // We try shrinking the widget down to size in an alternating pattern, shrink 1 in @@ -127,11 +135,10 @@ public class ReorderAlgorithm { // and not by the views hash which is "random". // The views are sorted twice, once for the X position and a second time for the Y position // to ensure same order everytime. - Comparator comparator = Comparator.comparing( - view -> ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellX() - ).thenComparing( - view -> ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellY() - ); + Comparator comparator = Comparator.comparing(view -> + ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellX()) + .thenComparing(view -> + ((CellLayoutLayoutParams) ((View) view).getLayoutParams()).getCellY()); List<View> views = solution.map.keySet().stream().sorted(comparator).toList(); for (View child : views) { if (child == ignoreView) continue; @@ -151,13 +158,15 @@ public class ReorderAlgorithm { // First we try to find a solution which respects the push mechanic. That is, // we try to find a solution such that no displaced item travels through another item // without also displacing that item. - if (attemptPushInDirection(intersectingViews, occupiedRect, direction, ignoreView, + if (attemptPushInDirection(intersectingViews, occupiedRect, direction, + ignoreView, solution)) { return true; } // Next we try moving the views as a block, but without requiring the push mechanic. - if (addViewsToTempLocation(intersectingViews, occupiedRect, direction, ignoreView, + if (addViewsToTempLocation(intersectingViews, occupiedRect, direction, + ignoreView, solution)) { return true; } @@ -171,8 +180,8 @@ public class ReorderAlgorithm { return true; } - private boolean addViewToTempLocation(View v, Rect rectOccupiedByPotentialDrop, int[] direction, - ItemConfiguration currentState) { + private boolean addViewToTempLocation(View v, Rect rectOccupiedByPotentialDrop, + int[] direction, ItemConfiguration currentState) { CellAndSpan c = currentState.map.get(v); boolean success = false; mCellLayout.mTmpOccupied.markCells(c, false); @@ -387,59 +396,63 @@ public class ReorderAlgorithm { /** * Returns a "reorder" if there is empty space without rearranging anything. * + * @param pixelX X coordinate in pixels in the screen + * @param pixelY Y coordinate in pixels in the screen + * @param spanX horizontal cell span + * @param spanY vertical cell span + * @param dragView view being dragged in reorder * @return the configuration that represents the found reorder */ - public ItemConfiguration dropInPlaceSolution(ReorderParameters reorderParameters) { - int[] result = mCellLayout.findNearestAreaIgnoreOccupied(reorderParameters.getPixelX(), - reorderParameters.getPixelY(), reorderParameters.getSpanX(), - reorderParameters.getSpanY(), new int[2]); + public ItemConfiguration dropInPlaceSolution(int pixelX, int pixelY, int spanX, + int spanY, View dragView) { + int[] result = mCellLayout.findNearestAreaIgnoreOccupied(pixelX, pixelY, spanX, spanY, + new int[2]); ItemConfiguration solution = new ItemConfiguration(); mCellLayout.copyCurrentStateToSolution(solution); solution.isSolution = !isConfigurationRegionOccupied( - new Rect(result[0], result[1], result[0] + reorderParameters.getSpanX(), - result[1] + reorderParameters.getSpanY()), solution, - reorderParameters.getDragView()); + new Rect(result[0], result[1], result[0] + spanX, result[1] + spanY), + solution, + dragView + ); if (!solution.isSolution) { return solution; } solution.cellX = result[0]; solution.cellY = result[1]; - solution.spanX = reorderParameters.getSpanX(); - solution.spanY = reorderParameters.getSpanY(); + solution.spanX = spanX; + solution.spanY = spanY; return solution; } - private boolean isConfigurationRegionOccupied(Rect region, ItemConfiguration configuration, - View ignoreView) { - return configuration.map - .entrySet() + private boolean isConfigurationRegionOccupied(Rect region, + ItemConfiguration configuration, View ignoreView) { + return configuration.map.entrySet() .stream() .filter(entry -> entry.getKey() != ignoreView) .map(Entry::getValue) - .anyMatch(cellAndSpan -> region.intersect( - cellAndSpan.cellX, - cellAndSpan.cellY, + .anyMatch(cellAndSpan -> region.intersect(cellAndSpan.cellX, cellAndSpan.cellY, cellAndSpan.cellX + cellAndSpan.spanX, - cellAndSpan.cellY + cellAndSpan.spanY - ) - ); + cellAndSpan.cellY + cellAndSpan.spanY)); } /** * Returns a "reorder" where we simply drop the item in the closest empty space, without moving * any other item in the way. * + * @param pixelX X coordinate in pixels in the screen + * @param pixelY Y coordinate in pixels in the screen + * @param spanX horizontal cell span + * @param spanY vertical cell span * @return the configuration that represents the found reorder */ - public ItemConfiguration closestEmptySpaceReorder(ReorderParameters reorderParameters) { + public ItemConfiguration closestEmptySpaceReorder(int pixelX, int pixelY, + int minSpanX, int minSpanY, int spanX, int spanY) { ItemConfiguration solution = new ItemConfiguration(); int[] result = new int[2]; int[] resultSpan = new int[2]; - mCellLayout.findNearestVacantArea(reorderParameters.getPixelX(), - reorderParameters.getPixelY(), reorderParameters.getMinSpanX(), - reorderParameters.getMinSpanY(), reorderParameters.getSpanX(), - reorderParameters.getSpanY(), result, resultSpan); + mCellLayout.findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, result, + resultSpan); if (result[0] >= 0 && result[1] >= 0) { mCellLayout.copyCurrentStateToSolution(solution); solution.cellX = result[0]; @@ -458,19 +471,32 @@ public class ReorderAlgorithm { * the workspace to make space for the new item, this function return a solution for that * reorder. * + * @param pixelX X coordinate in the screen of the dragView in pixels + * @param pixelY Y coordinate in the screen of the dragView in pixels + * @param minSpanX minimum horizontal span the item can be shrunk to + * @param minSpanY minimum vertical span the item can be shrunk to + * @param spanX occupied horizontal span + * @param spanY occupied vertical span + * @param dragView the view of the item being draged * @return returns a solution for the given parameters, the solution contains all the icons and * the locations they should be in the given solution. */ - public ItemConfiguration calculateReorder(ReorderParameters reorderParameters) { - getDirectionVectorForDrop(reorderParameters, mCellLayout.mDirectionVector); + public ItemConfiguration calculateReorder(int pixelX, int pixelY, int minSpanX, + int minSpanY, int spanX, int spanY, View dragView) { + getDirectionVectorForDrop(pixelX, pixelY, spanX, spanY, dragView, + mCellLayout.mDirectionVector); - ItemConfiguration dropInPlaceSolution = dropInPlaceSolution(reorderParameters); + ItemConfiguration dropInPlaceSolution = dropInPlaceSolution(pixelX, pixelY, spanX, spanY, + dragView); // Find a solution involving pushing / displacing any items in the way - ItemConfiguration swapSolution = findReorderSolution(reorderParameters, true); + ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, + minSpanY, spanX, spanY, mCellLayout.mDirectionVector, dragView, true, + new ItemConfiguration()); // We attempt the approach which doesn't shuffle views at all - ItemConfiguration closestSpaceSolution = closestEmptySpaceReorder(reorderParameters); + ItemConfiguration closestSpaceSolution = closestEmptySpaceReorder(pixelX, pixelY, minSpanX, + minSpanY, spanX, spanY); // If the reorder solution requires resizing (shrinking) the item being dropped, we instead // favor a solution in which the item is not resized, but @@ -510,26 +536,21 @@ public class ReorderAlgorithm { * those cells. Instead we use some heuristics to often lock the vector to up, down, left * or right, which helps make pushing feel right. */ - public void getDirectionVectorForDrop(ReorderParameters reorderParameters, - int[] resultDirection) { + private void getDirectionVectorForDrop(int dragViewCenterX, int dragViewCenterY, int spanX, + int spanY, View dragView, int[] resultDirection) { //TODO(adamcohen) b/151776141 use the items visual center for the direction vector int[] targetDestination = new int[2]; - mCellLayout.findNearestAreaIgnoreOccupied(reorderParameters.getPixelX(), - reorderParameters.getPixelY(), reorderParameters.getSpanX(), - reorderParameters.getSpanY(), targetDestination); + mCellLayout.findNearestAreaIgnoreOccupied(dragViewCenterX, dragViewCenterY, spanX, spanY, + targetDestination); Rect dragRect = new Rect(); - mCellLayout.cellToRect(targetDestination[0], targetDestination[1], - reorderParameters.getSpanX(), reorderParameters.getSpanY(), dragRect); - dragRect.offset(reorderParameters.getPixelX() - dragRect.centerX(), - reorderParameters.getPixelY() - dragRect.centerY()); + mCellLayout.cellToRect(targetDestination[0], targetDestination[1], spanX, spanY, dragRect); + dragRect.offset(dragViewCenterX - dragRect.centerX(), dragViewCenterY - dragRect.centerY()); Rect region = new Rect(targetDestination[0], targetDestination[1], - targetDestination[0] + reorderParameters.getSpanX(), - targetDestination[1] + reorderParameters.getSpanY()); - Rect dropRegionRect = mCellLayout.getIntersectingRectanglesInRegion(region, - reorderParameters.getDragView()); + targetDestination[0] + spanX, targetDestination[1] + spanY); + Rect dropRegionRect = mCellLayout.getIntersectingRectanglesInRegion(region, dragView); if (dropRegionRect == null) dropRegionRect = new Rect(region); int dropRegionSpanX = dropRegionRect.width(); @@ -538,17 +559,13 @@ public class ReorderAlgorithm { mCellLayout.cellToRect(dropRegionRect.left, dropRegionRect.top, dropRegionRect.width(), dropRegionRect.height(), dropRegionRect); - int deltaX = (dropRegionRect.centerX() - reorderParameters.getPixelX()) - / reorderParameters.getSpanX(); - int deltaY = (dropRegionRect.centerY() - reorderParameters.getPixelY()) - / reorderParameters.getSpanY(); + int deltaX = (dropRegionRect.centerX() - dragViewCenterX) / spanX; + int deltaY = (dropRegionRect.centerY() - dragViewCenterY) / spanY; - if (dropRegionSpanX == mCellLayout.getCountX() - || reorderParameters.getSpanX() == mCellLayout.getCountX()) { + if (dropRegionSpanX == mCellLayout.getCountX() || spanX == mCellLayout.getCountX()) { deltaX = 0; } - if (dropRegionSpanY == mCellLayout.getCountY() - || reorderParameters.getSpanY() == mCellLayout.getCountY()) { + if (dropRegionSpanY == mCellLayout.getCountY() || spanY == mCellLayout.getCountY()) { deltaY = 0; } |