This is an update with a more general solution. Now it handles the hide and “skips the crash” of the standard behavior of the lower view.
The following solution uses a custom BottomSheetBehavior . Here is a short video of a small application based on your hosted application with custom behavior:

MyBottomSheetBehavior extends BottomSheetBehavior and makes a heavy lift for the desired behavior. MyBottomSheetBehavior is passive until the NestedScrollView reaches the bottom scroll limit. onNestedScroll() determines that the limit has been reached and shifts the bottom sheet by the amount of scrolling until the offset for the fully expanded bottom sheet is reached. This is expansion logic.
As soon as the bottom sheet is released from the bottom, the bottom sheet is considered “captured” until the user lifts a finger from the screen. While the bottom sheet is captured, onNestPreScroll() handles the movement of the bottom sheet at the bottom of the screen. This is collapsing logic.
BottomSheetBehavior provides no means to manipulate the bottom sheet except to collapse or expand it completely. Other functionalities that are needed are blocked in the individually-private functions of the underlying behavior. To get around this, I created a new class called BottomSheetBehaviorAccessors that shares the package ( android.support.design.widget ) with the stock behavior. This class provides access to some private packages that are used in the new behavior.
MyBottomSheetBehavior also supports BottomSheetBehavior.BottomSheetCallback and other common functions.
MyBottomSheetBehavior.java
public class MyBottomSheetBehavior<V extends View> extends BottomSheetBehaviorAccessors<V> { // The bottom sheet that interests us. private View mBottomSheet; // Offset when sheet is expanded. private int mMinOffset; // Offset when sheet is collapsed. private int mMaxOffset; // This is the bottom of the bottom sheet parent. private int mParentBottom; // True if the bottom sheet is being moved through nested scrolls from NestedScrollView. private boolean mSheetCaptured = false; // True if the bottom sheet is touched directly and being dragged. private boolean mIsheetTouched = false; // Set to true on ACTION_DOWN on the NestedScrollView private boolean mScrollStarted = false; @SuppressWarnings("unused") public MyBottomSheetBehavior() { } @SuppressWarnings("unused") public MyBottomSheetBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { mSheetCaptured = false; mIsheetTouched = parent.isPointInChildBounds(child, (int) ev.getX(), (int) ev.getY()); mScrollStarted = !mIsheetTouched; } return super.onInterceptTouchEvent(parent, child, ev); } @Override public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { mMinOffset = Math.max(0, parent.getHeight() - child.getHeight()); mMaxOffset = Math.max(parent.getHeight() - getPeekHeight(), mMinOffset); mBottomSheet = child; mParentBottom = parent.getBottom(); return super.onLayoutChild(parent, child, layoutDirection); } @Override public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) { if (dy >= 0 || !mSheetCaptured || type != ViewCompat.TYPE_TOUCH || !(target instanceof NestedScrollView)) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); return; } // Pointer moving downward (dy < 0: scrolling toward top of data) if (child.getTop() - dy <= mMaxOffset) { // Dragging... ViewCompat.offsetTopAndBottom(child, -dy); setStateInternalAccessor(STATE_DRAGGING); consumed[1] = dy; } else if (isHideable()) { // Hide... ViewCompat.offsetTopAndBottom(child, Math.min(-dy, mParentBottom - child.getTop())); consumed[1] = dy; } else if (mMaxOffset - child.getTop() > 0) { // Collapsed... ViewCompat.offsetTopAndBottom(child, mMaxOffset - child.getTop()); consumed[1] = dy; } if (consumed[1] != 0) { dispatchOnSlideAccessor(child.getTop()); } } @Override public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { if (dyUnconsumed <= 0 || !(target instanceof NestedScrollView) || type != ViewCompat.TYPE_TOUCH || getState() == STATE_HIDDEN) { mSheetCaptured = false; } else if (!mSheetCaptured) { // Capture the bottom sheet only if it is at its collapsed height. mSheetCaptured = isSheetCollapsed(); } if (!mSheetCaptured) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); return; } /* If the pointer is moving upward (dyUnconsumed > 0) and the scroll view isn't consuming scroll (dyConsumed == 0) then the scroll view must be at the end of its scroll. */ if (child.getTop() - dyUnconsumed < mMinOffset) { // Expanded... ViewCompat.offsetTopAndBottom(child, mMinOffset - child.getTop()); } else { // Dragging... ViewCompat.offsetTopAndBottom(child, -dyUnconsumed); setStateInternalAccessor(STATE_DRAGGING); } dispatchOnSlideAccessor(child.getTop()); } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { if (mScrollStarted) { // Ignore initial call to this method before anything has happened. mScrollStarted = false; } else if (!mIsheetTouched) { snapBottomSheet(); } super.onStopNestedScroll(coordinatorLayout, child, target); } private void snapBottomSheet() { if ((mMaxOffset - mBottomSheet.getTop()) > (mMaxOffset - mMinOffset) / 2) { setState(BottomSheetBehavior.STATE_EXPANDED); } else if (shouldHideAccessor(mBottomSheet, 0)) { setState(BottomSheetBehavior.STATE_HIDDEN); } else { setState(BottomSheetBehavior.STATE_COLLAPSED); } } private boolean isSheetCollapsed() { return mBottomSheet.getTop() == mMaxOffset; } @SuppressWarnings("unused") private static final String TAG = "MyBottomSheetBehavior"; }
BottomSheetBehaviorAccessors
package android.support.design.widget; // important! // A "friend" class to provide access to some package-private methods in `BottomSheetBehavior`. public class BottomSheetBehaviorAccessors<V extends View> extends BottomSheetBehavior<V> { @SuppressWarnings("unused") protected BottomSheetBehaviorAccessors() { } @SuppressWarnings("unused") public BottomSheetBehaviorAccessors(Context context, AttributeSet attrs) { super(context, attrs); } protected void setStateInternalAccessor(int state) { super.setStateInternal(state); } protected void dispatchOnSlideAccessor(int top) { super.dispatchOnSlide(top); } protected boolean shouldHideAccessor(View child, float yvel) { return mHideable && super.shouldHide(child, yvel); } @SuppressWarnings("unused") private static final String TAG = "BehaviorAccessor"; }
MainActivity.java
public class MainActivity extends AppCompatActivity{ private View mBottomSheet; MyBottomSheetBehavior<View> mBehavior; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayShowTitleEnabled(false); int peekHeight = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_peek_height);
activity_main.xml
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:stateListAnimator="@null" android:theme="@style/AppTheme.AppBarOverlay" app:expanded="false" app:layout_behavior="android.support.design.widget.AppBarLayout$Behavior"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsingToolbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:statusBarScrim="?attr/colorPrimaryDark"> <ImageView android:layout_width="match_parent" android:layout_height="250dp" android:layout_marginTop="?attr/actionBarSize" android:scaleType="centerCrop" android:src="@drawable/seascape1" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="1.0" tools:ignore="ContentDescription" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <com.example.bottomsheetoverscroll.MyNestedScrollView android:id="@+id/nestedScrollView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_blue_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_red_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_blue_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_red_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_blue_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_red_light" /> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="@android:color/holo_green_light" /> </LinearLayout> </com.example.bottomsheetoverscroll.MyNestedScrollView> <TextView android:id="@+id/bottomSheet" android:layout_width="300dp" android:layout_height="400dp" android:layout_gravity="center_horizontal" android:background="@android:color/white" android:text="Bottom Sheet" android:textAlignment="center" android:textSize="24sp" android:textStyle="bold" app:layout_behavior="com.example.bottomsheetoverscroll.MyBottomSheetBehavior" /> </android.support.design.widget.CoordinatorLayout>