@Override public void onViewDragStateChanged(int state) { switch (state) { case ViewDragHelper.STATE_SETTLING: case ViewDragHelper.STATE_DRAGGING: { mScrollingHeaderByHelper = false; break; } case ViewDragHelper.STATE_IDLE: { if (mTime > 0 && !Float.isNaN(mVelocity)) { final float velocity = mVelocity; if (velocity < 0 && mDrawer.getHeaderTop() <= mDrawer.getHeaderTopMinimum()) { mDrawer.flingCallback(-velocity); } } mTime = -1; mDx = Float.NaN; mDy = Float.NaN; mVelocity = Float.NaN; mScrollingHeaderByHelper = false; break; } } super.onViewDragStateChanged(state); }
@Override public void onViewReleased(View releasedChild, float xvel, float yvel) { mDrawer.mDragHelper.flingCapturedView( mDrawer.getPaddingLeft(), mDrawer.getHeaderTopMinimum(), mDrawer.getPaddingLeft(), mDrawer.getHeaderTopMaximum()); ViewCompat.postInvalidateOnAnimation(mDrawer); }
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { final int top = mDrawer.getHeaderTop(), min = mDrawer.getHeaderTopMinimum(); final boolean showingFullContent = top <= min, flingUp = velocityY < 0; final boolean verticalFling = Math.abs(velocityY) > Math.abs(velocityX); if (!verticalFling) return true; if (showingFullContent) { if (flingUp) { // Fling list up when showing full content if (mDrawer.isScrollingContentCallback()) { mDrawer.flingCallback(-velocityY); } } else { // Fling down when list reached top and not dragging user ViewDragHelper, // so we fling header down here if (!mDrawer.canScrollCallback(1) && !mDrawer.isUsingDragHelper()) { mDrawer.flingHeader(velocityY); } } } else { // Header still visible } return true; }
@Override public void offsetTopAndBottom(int offset) { super.offsetTopAndBottom(offset); mParent.notifyOffsetChanged(); }
public int getHeaderTopMinimum() { return mParent.getPaddingTop() - mHeaderView.getHeight(); }
public int getHeaderTopMaximum() { return mParent.getPaddingTop(); }
@Override public boolean onDown(MotionEvent e) { mDrawer.setScrollingHeaderByGesture(false); mDrawer.setScrollingContentCallback(false); return true; }
@Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!mDrawer.isUsingDragHelper() && mDrawer.isValidScroll(distanceY, distanceX)) { final int offset = mDrawer.getHeaderTop(), min = mDrawer.getHeaderTopMinimum(); if (!mDrawer.canScrollCallback(-1)) { if (distanceY < 0) { if (!mDrawer.isScrollingHeaderByHelper()) { mDrawer.offsetHeaderBy(Math.round(-distanceY)); } mDrawer.setScrollingHeaderByGesture(true); } else if (distanceY > 0 && offset > min) { // Scrolling up when scrolling to list top, so we cancel touch event and scrolling // header up mDrawer.cancelTouchCallback(); if (!mDrawer.isScrollingHeaderByHelper()) { mDrawer.offsetHeaderBy(Math.round(-distanceY)); } } else if (offset <= min) { mDrawer.scrollByCallback(-distanceX); } } } return true; }
@Override public int clampViewPositionVertical(final View child, final int top, final int dy) { final int current = mDrawer.getHeaderTop(); if (!Float.isNaN(mDx) && mDrawer.isValidScroll(mDx, dy)) { mScrollingHeaderByHelper = false; return current; } if (dy > 0 && mDrawer.canScrollCallback(-dy) && mDrawer.isTouchingScrollableContent()) { if (!mDrawer.isUsingDragHelper()) { // Scrolling up while list still has space to scroll, so make header still mScrollingHeaderByHelper = false; return current; } else { mDrawer.scrollByCallback(-dy); mScrollingHeaderByHelper = false; return current; } } final int min = mDrawer.getHeaderTopMinimum(), max = mDrawer.getHeaderTopMaximum(); if (top < min && mDrawer.isTouchingScrollableContent() && mDrawer.isUsingDragHelper()) { mDrawer.scrollByCallback(-dy); } mScrollingHeaderByHelper = true; return MathUtils.clamp(top, min, max); }
@Override public int clampViewPositionHorizontal(View child, int left, int dx) { mDx = dx; return mDrawer.getPaddingLeft(); }
@Override public int getViewVerticalDragRange(View child) { return mDrawer.getScrollRange(); }