Fixes to touch handling in all apps pull up work

b/28917826
- Fast scroll bar works even when it's at the top of the recycler view
- Pull down only happens ONLY IF the thumb of the scroll bar is at top
- When container is touched during sliding down animation,
translation should not jump

Change-Id: Ic1d9a4aa77332cc0a7582556f893053003224dd3
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index a680169..fd0045e 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -27,7 +27,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 
 import com.android.launcher3.util.Thunk;
@@ -293,7 +292,7 @@
     /**
      * Returns whether the specified points are near the scroll bar bounds.
      */
-    private boolean isNearThumb(int x, int y) {
+    public boolean isNearThumb(int x, int y) {
         mTmpRect.set(mThumbOffset.x, mThumbOffset.y, mThumbOffset.x + mThumbWidth,
                 mThumbOffset.y + mThumbHeight);
         mTmpRect.inset(mTouchInset, mTouchInset);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 2c9f810..a74c4c5 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -257,9 +257,24 @@
         mAppsRecyclerView.scrollToTop();
     }
 
-    public boolean isScrollAtTop() {
-        return ((LinearLayoutManager) mAppsRecyclerView.getLayoutManager())
-                .findFirstVisibleItemPosition() == 1;
+    /**
+     * Returns whether the view itself will handle the touch event or not.
+     */
+    public boolean shouldContainerScroll(float x, float y) {
+        int[] point = new int[2];
+        point[0] = (int) x;
+        point[1] = (int) y;
+        Utilities.mapCoordInSelfToDescendent(mAppsRecyclerView, this, point);
+
+        // if the MotionEvent is inside the thumb, container should not be pulled down.
+        if (mAppsRecyclerView.getScrollBar().isNearThumb(point[0], point[1])){
+             return false;
+        }
+        // If scroller is at the very top, then it's okay for the container to be pulled down.
+        if (Float.compare(0f, mAppsRecyclerView.getScrollBar().getThumbOffset().y) == 0) {
+            return true;
+        }
+        return false;
     }
     /**
      * Focuses the search field and begins an app search.
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 829a566..d70ee47 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -9,9 +9,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
 
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.Hotseat;
@@ -39,7 +37,7 @@
      private final Interpolator mAccelInterpolator = new AccelerateInterpolator(1f);
 
     private static final float ANIMATION_DURATION = 2000;
-    private static final float FINAL_ALPHA = .6f;
+    private static final float FINAL_ALPHA = .65f;
 
     private AllAppsContainerView mAppsView;
     private Workspace mWorkspace;
@@ -60,6 +58,7 @@
     private float mCurY;
 
     private AnimatorSet mCurrentAnimation;
+    private boolean mNoIntercept;
 
     public AllAppsTransitionController(Launcher launcher) {
         mLauncher = launcher;
@@ -70,11 +69,20 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         init();
-        if (mWorkspace.isInOverviewMode() || mLauncher.isWidgetsViewVisible()) {
-            return false;
-        }
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mDetector.setAllAppsState(mLauncher.isAllAppsVisible(), mAppsView.isScrollAtTop());
+            mNoIntercept = false;
+            if (mLauncher.getWorkspace().isInOverviewMode() || mLauncher.isWidgetsViewVisible()) {
+                mNoIntercept = true;
+            }
+            if (mLauncher.isAllAppsVisible() &&
+                    !mAppsView.shouldContainerScroll(ev.getX(), ev.getY())) {
+                mNoIntercept = true;
+            }
+        }
+        if (mNoIntercept) {
+            return false;
+        } else {
+            mDetector.setScrollDirectionDown(mLauncher.isAllAppsVisible());
         }
         mDetector.onTouchEvent(ev);
         return mDetector.mScrolling;
diff --git a/src/com/android/launcher3/allapps/VerticalPullDetector.java b/src/com/android/launcher3/allapps/VerticalPullDetector.java
index 12d414e..0c3698d 100644
--- a/src/com/android/launcher3/allapps/VerticalPullDetector.java
+++ b/src/com/android/launcher3/allapps/VerticalPullDetector.java
@@ -14,9 +14,7 @@
     private static final boolean DBG = false;
 
     private float mTouchSlop;
-
-    private boolean mAllAppsVisible;
-    private boolean mAllAppsScrollAtTop;
+    private boolean mScrollDown; // if false, only scroll up will be reported.
 
     /**
      * The minimum release velocity in pixels per millisecond that triggers fling..
@@ -32,20 +30,20 @@
     /* Scroll state, this is set to true during dragging and animation. */
     boolean mScrolling;
 
-    float mDownX;
-    float mDownY;
-    float mDownMillis;
+    private float mDownX;
+    private float mDownY;
+    private float mDownMillis;
 
-    float mLastY;
-    float mLastMillis;
+    private float mLastY;
+    private float mLastMillis;
 
-    float mVelocity;
-    float mLastDisplacement;
-    float mDisplacementY;
-    float mDisplacementX;
+    private float mVelocity;
+    private float mLastDisplacement;
+    private float mDisplacementY;
+    private float mDisplacementX;
 
     /* scroll started during previous animation */
-    boolean mSubtractSlop = true;
+    private boolean mSubtractSlop = true;
 
     /* Client of this gesture detector can register a callback. */
     Listener mListener;
@@ -67,20 +65,19 @@
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     }
 
-    public void setAllAppsState(boolean allAppsVisible, boolean scrollAtTop) {
-        mAllAppsVisible = allAppsVisible;
-        mAllAppsScrollAtTop = scrollAtTop;
+    public void setScrollDirectionDown(boolean scrollDown) {
+        mScrollDown = scrollDown;
     }
 
     private boolean shouldScrollStart() {
         float deltaY = Math.abs(mDisplacementY);
         float deltaX = Math.max(Math.abs(mDisplacementX), 1);
-        if (mAllAppsVisible && mDisplacementY > mTouchSlop && mAllAppsScrollAtTop) {
+        if (mScrollDown && mDisplacementY > mTouchSlop) {
             if (deltaY > deltaX) {
                 return true;
             }
         }
-        if (!mAllAppsVisible && mDisplacementY < -mTouchSlop) {
+        if (!mScrollDown && mDisplacementY < -mTouchSlop) {
             if (deltaY > deltaX) {
                 return true;
             }
@@ -140,6 +137,7 @@
 
     private boolean reportScrollStart(boolean recatch) {
         mListener.onScrollStart(!recatch);
+        mSubtractSlop = !recatch;
         if (DBG) {
             Log.d(TAG, "onScrollStart recatch:" + recatch);
         }
@@ -153,11 +151,15 @@
                 Log.d(TAG, String.format("onScroll disp=%.1f, velocity=%.1f",
                         mDisplacementY, mVelocity));
             }
-            if (mDisplacementY > 0) {
-                return mListener.onScroll(mDisplacementY - mTouchSlop, mVelocity);
-            } else {
-                return mListener.onScroll(mDisplacementY + mTouchSlop, mVelocity);
+            float subtractDisplacement = 0f;
+            if (mSubtractSlop) {
+                if (mDisplacementY > 0) {
+                    subtractDisplacement = mTouchSlop;
+                } else {
+                    subtractDisplacement = -mTouchSlop;
+                }
             }
+            return mListener.onScroll(mDisplacementY - subtractDisplacement, mVelocity);
         }
         return true;
     }