Snap to relative position to snappd task when dismissing

- Calculate the diff to snapped page scroll and apply in onLayout, so tasks won't jump after dismiss when not in snapped position
- In grid, always keep the relateive snapped page unchanged to avoid jump

Bug: 188793333
Test: manual
Change-Id: Id11c2d700dc55440de39cc7409d06a712cedc9bc
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index eec0a71..c7924e4 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2438,12 +2438,15 @@
                     resetTaskVisuals();
 
                     int pageToSnapTo = mCurrentPage;
-                    if (finalNextFocusedTaskView != null) {
-                        pageToSnapTo = indexOfChild(finalNextFocusedTaskView);
-                    }
-                    if (dismissedIndex < pageToSnapTo || pageToSnapTo == (taskCount - 1)) {
+                    if ((dismissedIndex < pageToSnapTo && !showAsGrid)
+                            || pageToSnapTo == taskCount - 1) {
                         pageToSnapTo -= 1;
                     }
+                    if (showAsGrid) {
+                        int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
+                        int currentPageScroll = getScrollForPage(pageToSnapTo);
+                        mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
+                    }
                     removeViewInLayout(dismissedTaskView);
                     mTopRowIdSet.remove(dismissedTaskId);
 
@@ -2456,12 +2459,11 @@
                             mFocusedTaskId = finalNextFocusedTaskView.getTaskId();
                             mTopRowIdSet.remove(mFocusedTaskId);
                             finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
-                            setCurrentPage(pageToSnapTo);
                         }
                         updateTaskSize(true);
                         // Update scroll and snap to page.
                         updateScrollSynchronously();
-                        snapToPageImmediately(pageToSnapTo);
+                        setCurrentPage(pageToSnapTo);
                         dispatchScrollChanged();
                     }
                 }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 204913a..1555e98 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -104,6 +104,10 @@
 
     @ViewDebug.ExportedProperty(category = "launcher")
     protected int mCurrentPage;
+    // Difference between current scroll position and mCurrentPage's page scroll. Used to maintain
+    // relative scroll position unchanged in updateCurrentPageScroll. Cleared when snapping to a
+    // page.
+    protected int mCurrentPageScrollDiff;
 
     @ViewDebug.ExportedProperty(category = "launcher")
     protected int mNextPage = INVALID_PAGE;
@@ -247,7 +251,7 @@
         // If the current page is invalid, just reset the scroll position to zero
         int newPosition = 0;
         if (0 <= mCurrentPage && mCurrentPage < getPageCount()) {
-            newPosition = getScrollForPage(mCurrentPage);
+            newPosition = getScrollForPage(mCurrentPage) + mCurrentPageScrollDiff;
         }
         mOrientationHandler.set(this, VIEW_SCROLL_TO, newPosition);
         mScroller.startScroll(mScroller.getCurrX(), 0, newPosition - mScroller.getCurrX(), 0);
@@ -452,6 +456,7 @@
      * to provide custom behavior during animation.
      */
     protected void onPageEndTransition() {
+        mCurrentPageScrollDiff = 0;
         AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
         AccessibilityManagerCompat.sendCustomAccessibilityEvent(getPageAt(mCurrentPage),
                 AccessibilityEvent.TYPE_VIEW_FOCUSED, null);