Merge "AppBarLayout fixes" into mnc-ub-dev
diff --git a/design/src/android/support/design/widget/AppBarLayout.java b/design/src/android/support/design/widget/AppBarLayout.java
index 4b910ba..eb7a962 100644
--- a/design/src/android/support/design/widget/AppBarLayout.java
+++ b/design/src/android/support/design/widget/AppBarLayout.java
@@ -369,6 +369,9 @@
                 if ((flags & LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED) != 0) {
                     // If they're set to enter collapsed, use the minimum height
                     range += ViewCompat.getMinimumHeight(child);
+                } else if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {
+                    // Only enter by the amount of the collapsed height
+                    range += childHeight - ViewCompat.getMinimumHeight(child);
                 } else {
                     // Else use the full height
                     range += childHeight;
@@ -379,7 +382,7 @@
                 break;
             }
         }
-        return mDownPreScrollRange = range;
+        return mDownPreScrollRange = Math.max(0, range - getTopInset());
     }
 
     /**
@@ -668,7 +671,7 @@
         private int mOffsetDelta;
 
         private boolean mSkipNestedPreScroll;
-        private boolean mWasFlung;
+        private boolean mWasNestedFlung;
 
         private ValueAnimatorCompat mAnimator;
 
@@ -743,14 +746,14 @@
         @Override
         public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl,
                 View target) {
-            if (!mWasFlung) {
+            if (!mWasNestedFlung) {
                 // If we haven't been flung then let's see if the current view has been set to snap
                 snapToChildIfNeeded(coordinatorLayout, abl);
             }
 
             // Reset the flags
             mSkipNestedPreScroll = false;
-            mWasFlung = false;
+            mWasNestedFlung = false;
             // Keep a reference to the previous nested scrolling child
             mLastNestedScrollingChildRef = new WeakReference<>(target);
         }
@@ -790,7 +793,7 @@
                 }
             }
 
-            mWasFlung = flung;
+            mWasNestedFlung = flung;
             return flung;
         }
 
@@ -907,6 +910,11 @@
             abl.resetPendingAction();
             mOffsetToChildIndexOnLayout = INVALID_POSITION;
 
+            // We may have changed size, so let's constrain the top and bottom offset correctly,
+            // just in case we're out of the bounds
+            setTopAndBottomOffset(
+                    MathUtils.constrain(getTopAndBottomOffset(), -abl.getTotalScrollRange(), 0));
+
             // Make sure we update the elevation
             dispatchOffsetUpdates(abl);
 
@@ -933,6 +941,12 @@
         }
 
         @Override
+        void onFlingFinished(CoordinatorLayout parent, AppBarLayout layout) {
+            // At the end of a manual fling, check to see if we need to snap to the edge-child
+            snapToChildIfNeeded(parent, layout);
+        }
+
+        @Override
         int getMaxDragOffset(AppBarLayout view) {
             return -view.getDownNestedScrollRange();
         }
diff --git a/design/src/android/support/design/widget/HeaderBehavior.java b/design/src/android/support/design/widget/HeaderBehavior.java
index 6e7a1c0..9924d48 100644
--- a/design/src/android/support/design/widget/HeaderBehavior.java
+++ b/design/src/android/support/design/widget/HeaderBehavior.java
@@ -247,8 +247,18 @@
             mFlingRunnable = new FlingRunnable(coordinatorLayout, layout);
             ViewCompat.postOnAnimation(layout, mFlingRunnable);
             return true;
+        } else {
+            onFlingFinished(coordinatorLayout, layout);
+            return false;
         }
-        return false;
+    }
+
+    /**
+     * Called when a fling has finished, or the fling was initiated but there wasn't enough
+     * velocity to start it.
+     */
+    void onFlingFinished(CoordinatorLayout parent, V layout) {
+        // no-op
     }
 
     /**
@@ -286,11 +296,14 @@
 
         @Override
         public void run() {
-            if (mLayout != null && mScroller != null && mScroller.computeScrollOffset()) {
-                setHeaderTopBottomOffset(mParent, mLayout, mScroller.getCurrY());
-
-                // Post ourselves so that we run on the next animation
-                ViewCompat.postOnAnimation(mLayout, this);
+            if (mLayout != null && mScroller != null) {
+                if (mScroller.computeScrollOffset()) {
+                    setHeaderTopBottomOffset(mParent, mLayout, mScroller.getCurrY());
+                    // Post ourselves so that we run on the next animation
+                    ViewCompat.postOnAnimation(mLayout, this);
+                } else {
+                    onFlingFinished(mParent, mLayout);
+                }
             }
         }
     }