From 0f12b6013da4a53b911dedd1e70a4783994a405b Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Wed, 26 Aug 2020 19:08:18 -0700 Subject: [PATCH] Delays removal of extra screen when dropping an app. This prevents a conflict between the scroll animation and layout transition caused by removing the screen. Since the extra screen is at the end of the workspace, this most commonly (only?) causes issues in RTL, as everything shifts to the left to fill the void of the empty screen. See bug for example video of the issue. With this change, the removal of the empty screen happens after Launcher finishes transitioning back to NORMAL state after dropping an icon/widget, rather than in onDragEnd. Note: There is a similar issue when placing a widget in RTL (even if not switching screens), but it's not made worse by this CL. Filed b/166531479. Demo: https://drive.google.com/file/d/1JTP81syjoBFe3_N2SOZHP5r5_RoCUWan/view?usp=sharing Fixes: 163382092 Change-Id: I55ed5af8e1d80dcc0d1b6502c3c5b068dc6f8722 --- src/com/android/launcher3/Workspace.java | 20 ++++++++++++++----- .../launcher3/WorkspaceLayoutManager.java | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 3be9ac7e07..3ef4bf6604 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -93,6 +93,7 @@ import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pageindicators.WorkspacePageIndicator; import com.android.launcher3.popup.PopupContainerWithArrow; +import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.WorkspaceTouchListener; @@ -437,10 +438,6 @@ public class Workspace extends PagedView enforceDragParity("onDragEnd", 0, 0); } - if (!mDeferRemoveExtraEmptyScreen) { - removeExtraEmptyScreen(mDragSourceInternal != null); - } - updateChildrenLayersEnabled(); mDragInfo = null; mOutlineProvider = null; @@ -658,6 +655,7 @@ public class Workspace extends PagedView convertFinalScreenToEmptyScreenIfNecessary(); if (hasExtraEmptyScreen()) { removeView(mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID)); + setCurrentPage(getNextPage()); mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID); mScreenOrder.removeValue(EXTRA_EMPTY_SCREEN_ID); @@ -1873,6 +1871,18 @@ public class Workspace extends PagedView }; } } + StateManager stateManager = mLauncher.getStateManager(); + stateManager.addStateListener(new StateManager.StateListener() { + @Override + public void onStateTransitionComplete(LauncherState finalState) { + if (finalState == NORMAL) { + if (!mDeferRemoveExtraEmptyScreen) { + removeExtraEmptyScreen(true /* stripEmptyScreens */); + } + stateManager.removeStateListener(this); + } + } + }); mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId, lp.cellX, lp.cellY, item.spanX, item.spanY); @@ -2453,7 +2463,7 @@ public class Workspace extends PagedView Runnable onAnimationCompleteRunnable = new Runnable() { @Override public void run() { - // Normally removeExtraEmptyScreen is called in Workspace#onDragEnd, but when + // Normally removeExtraEmptyScreen is called in Workspace#onDrop, but when // adding an item that may not be dropped right away (due to a config activity) // we defer the removal until the activity returns. deferRemoveExtraEmptyScreen(); diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java index c3d4aeb745..ea887cc5eb 100644 --- a/src/com/android/launcher3/WorkspaceLayoutManager.java +++ b/src/com/android/launcher3/WorkspaceLayoutManager.java @@ -28,7 +28,7 @@ public interface WorkspaceLayoutManager { String TAG = "Launcher.Workspace"; - // The screen id used for the empty screen always present to the right. + // The screen id used for the empty screen always present at the end. int EXTRA_EMPTY_SCREEN_ID = -201; // The is the first screen. It is always present, even if its empty. int FIRST_SCREEN_ID = 0;