Fix BottomSheetBehavior for non-last child

The bottom sheet does not need to be the last child of CoordinatorLayout
any more.

Bug: 26552452
Change-Id: I180a18ed4f5fcf7b4d026955cae6391a2a2bc19b
diff --git a/design/src/android/support/design/widget/BottomSheetBehavior.java b/design/src/android/support/design/widget/BottomSheetBehavior.java
index c7e7f3d..22c35f9 100644
--- a/design/src/android/support/design/widget/BottomSheetBehavior.java
+++ b/design/src/android/support/design/widget/BottomSheetBehavior.java
@@ -138,6 +138,8 @@
 
     private int mActivePointerId;
 
+    private int mInitialY;
+
     /**
      * Default constructor for instantiating BottomSheetBehaviors.
      */
@@ -229,17 +231,27 @@
                 }
                 break;
             case MotionEvent.ACTION_DOWN:
-                int x = (int) event.getX();
-                int y = (int) event.getY();
+                int initialX = (int) event.getX();
+                mInitialY = (int) event.getY();
                 View scroll = mNestedScrollingChildRef.get();
-                if (scroll != null && parent.isPointInChildBounds(scroll, x, y)) {
+                if (scroll != null && parent.isPointInChildBounds(scroll, initialX, mInitialY)) {
                     mActivePointerId = event.getPointerId(event.getActionIndex());
                 }
                 mIgnoreEvents = mActivePointerId == MotionEvent.INVALID_POINTER_ID &&
-                        !parent.isPointInChildBounds(child, x, y);
+                        !parent.isPointInChildBounds(child, initialX, mInitialY);
                 break;
         }
-        return !mIgnoreEvents && mViewDragHelper.shouldInterceptTouchEvent(event);
+        if (!mIgnoreEvents && mViewDragHelper.shouldInterceptTouchEvent(event)) {
+            return true;
+        }
+        // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because
+        // it is not the top most view of its parent. This is not necessary when the touch event is
+        // happening over the scrolling content as nested scrolling logic handles that case.
+        View scroll = mNestedScrollingChildRef.get();
+        return action == MotionEvent.ACTION_MOVE && scroll != null &&
+                !mIgnoreEvents && mState != STATE_DRAGGING &&
+                !parent.isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY()) &&
+                Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop();
     }
 
     @Override
@@ -260,6 +272,13 @@
             mVelocityTracker = VelocityTracker.obtain();
         }
         mVelocityTracker.addMovement(event);
+        // The ViewDragHelper tries to capture only the top-most View. We have to explicitly tell it
+        // to capture the bottom sheet in case it is not captured and the touch slop is passed.
+        if (action == MotionEvent.ACTION_MOVE) {
+            if (Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop()) {
+                mViewDragHelper.captureChildView(child, event.getPointerId(event.getActionIndex()));
+            }
+        }
         return true;
     }