@Override public void computeScroll() { if (mOverScroller.computeScrollOffset()) { scrollTo(0, mOverScroller.getCurrY()); invalidate(); } }
@Override public void computeScroll() { if (mScroller.computeScrollOffset()) { // This is called at drawing time by ViewGroup. We don't want to // re-show the scrollbars at this point, which scrollTo will do, // so we replicate most of scrollTo here. // // It's a little odd to call onScrollChanged from inside the drawing. // // It is, except when you remember that computeScroll() is used to // animate scrolling. So unless we want to defer the onScrollChanged() // until the end of the animated scrolling, we don't really have a // choice here. // // I agree. The alternative, which I think would be worse, is to post // something and tell the subclasses later. This is bad because there // will be a window where mScrollX/Y is different from what the app // thinks it is. // int oldX = getScrollX(); // mScrollX; int oldY = getScrollY(); // mScrollY; int x = mScroller.getCurrX(); int y = mScroller.getCurrY(); CFUtil.Log("sx=" + x + ", sy=" + y); if (oldX != x || oldY != y) { final int rangeY = getScrollRangeY(); // final int overscrollMode = getOverScrollMode(); // final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || // (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); // overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range, // 0, mOverflingDistance, false); scrollTo(x, y); onScrollChanged(getScrollX(), getScrollY(), oldX, oldY); // if (canOverscroll) { // if (y < 0 && oldY >= 0) { // mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity()); // } else if (y > range && oldY <= range) { // mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity()); // } // } } postInvalidate(); // if (!awakenScrollBars()) { // // Keep on drawing until the animation has finished. // postInvalidateOnAnimation(); // } } // else { // if (mFlingStrictSpan != null) { // mFlingStrictSpan.finish(); // mFlingStrictSpan = null; // } // } }
public boolean computeScrollOffset() { if (isPreGingerbread) { return scroller.computeScrollOffset(); } else { overScroller.computeScrollOffset(); return overScroller.computeScrollOffset(); } }
// Returns the distance that over the scroll limit. public int startScroll(int distance, int min, int max) { int currPosition = mScroller.getCurrX(); int finalPosition = mScroller.isFinished() ? currPosition : mScroller.getFinalX(); int newPosition = Utils.clamp(finalPosition + distance, min, max); if (newPosition != currPosition) { mScroller.startScroll(currPosition, 0, newPosition - currPosition, 0, 0); } return finalPosition + distance - newPosition; }
@Override public boolean computeScrollOffset() { // Workaround for first scroll returning 0 for the direction of the edge it hits. // Simply recompute values. if (mFirstScroll) { mScroller.computeScrollOffset(); mFirstScroll = false; } return mScroller.computeScrollOffset(); }
@Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { mRect.offsetTo(mScroller.getCurrX(), mScroller.getCurrY()); ViewCompat.postInvalidateOnAnimation(this); } }
/** Called from the view draw, computes the next scroll. */ boolean computeScroll() { Log.d(TAG, "computeScroll: "); if (mScroller.computeScrollOffset()) { float scroll = scrollRangeToProgress(mScroller.getCurrY()); setStackScrollRaw(scroll); if (mCb != null) { mCb.onScrollChanged(scroll); } return true; } return false; }
@Override public void computeScroll() { if (mScroller.computeScrollOffset()) { // This is called at drawing time by ViewGroup. We don't want to // re-show the scrollbars at this point, which scrollTo will do, // so we replicate most of scrollTo here. // // It's a little odd to call onScrollChanged from inside the drawing. // // It is, except when you remember that computeScroll() is used to // animate scrolling. So unless we want to defer the onScrollChanged() // until the end of the animated scrolling, we don't really have a // choice here. // // I agree. The alternative, which I think would be worse, is to post // something and tell the subclasses later. This is bad because there // will be a window where mScrollX/Y is different from what the app // thinks it is. // int oldX = getScrollX(); int oldY = getScrollY(); int x = mScroller.getCurrX(); int y = mScroller.getCurrY(); if (oldX != x || oldY != y) { final int range = getScrollRange(); final int overscrollMode = getOverScrollMode(); final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); overScrollBy(x - oldX, y - oldY, oldX, oldY, range, 0, mOverflingDistance, 0, false); onScrollChanged(getScrollX(), getScrollY(), oldX, oldY); } if (!awakenScrollBars()) { postInvalidateOnAnimation(); } } else { int scrollX = getScrollX(); int finalX = getScrollXFromFinalX(scrollX); if (!mIsBeingDragged && scrollX != finalX) { if (mScroller.springBack(getScrollX(), getScrollY(), finalX, finalX, 0, 0)) { postInvalidateOnAnimation(); } } } }
public static void fling( Object paramObject, int paramInt1, int paramInt2, int paramInt3, int paramInt4, int paramInt5, int paramInt6, int paramInt7, int paramInt8, int paramInt9, int paramInt10) { ((OverScroller) paramObject) .fling( paramInt1, paramInt2, paramInt3, paramInt4, paramInt5, paramInt6, paramInt7, paramInt8, paramInt9, paramInt10); }
/** Animates the stack scroll */ void animateScroll(float curScroll, float newScroll, final Runnable postRunnable) { // Finish any current scrolling animations Log.d(TAG, "animateScroll: "); if (mScrollAnimator != null && mScrollAnimator.isRunning()) { setStackScroll(mFinalAnimatedScroll); mScroller.startScroll(0, progressToScrollRange(mFinalAnimatedScroll), 0, 0, 0); } stopScroller(); stopBoundScrollAnimation(); mFinalAnimatedScroll = newScroll; mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll); mScrollAnimator.setDuration(mConfig.taskStackScrollDuration); mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator); mScrollAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { setStackScroll((Float) animation.getAnimatedValue()); } }); mScrollAnimator.addListener( new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (postRunnable != null) { postRunnable.run(); } mScrollAnimator.removeAllListeners(); } }); mScrollAnimator.start(); }
public void forceFinished(boolean finished) { if (isOld) { ((Scroller) scroller).forceFinished(finished); } else { ((OverScroller) scroller).forceFinished(finished); } }
// @SuppressLint("NewApi") public void fling(int velocityX, int velocityY) { CFUtil.Log("fling " + velocityY + ", " + velocityY); if (getChildCount() > 0) { int height = getHeight() - getPaddingBottom() - getPaddingTop(); int width = getWidth() - getPaddingLeft() - getPaddingRight(); // int right = getChildAt(getChildCount()-1).getWidth(); // int bottom = getChildAt(getChildCount()-1).getHeight(); // mScroller.springBack(getScrollX(), getScrollY(), 0, width, 0, getScrollRange()); // mScroller.startScroll(getScrollX(), getScrollY(), velocityX, velocityY, 1000); mScroller.fling( getScrollX(), getScrollY(), velocityX, velocityY, // 0, Math.max(0, right - width), // 0, Math.max(0, bottom - height), 0, Math.max(0, getScrollRangeX()), 0, Math.max(0, getScrollRangeY()), width / 2, height / 2); // if (mFlingStrictSpan == null) { // mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling"); // } // postInvalidateOnAnimation(); postInvalidate(); } }
public int getCurrY() { if (isPreGingerbread) { return scroller.getCurrY(); } else { return overScroller.getCurrY(); } }
public void forceFinished(boolean finished) { if (isPreGingerbread) { scroller.forceFinished(finished); } else { overScroller.forceFinished(finished); } }
public boolean isFinished() { if (isPreGingerbread) { return scroller.isFinished(); } else { return overScroller.isFinished(); } }
// Starts the fling animation. Called both as a response to a fling gesture and as via the // public WebView#flingScroll(int, int) API. public void flingScroll(int velocityX, int velocityY) { final int scrollX = mDelegate.getContainerViewScrollX(); final int scrollY = mDelegate.getContainerViewScrollY(); final int rangeX = computeMaximumHorizontalScrollOffset(); final int rangeY = computeMaximumVerticalScrollOffset(); mScroller.fling(scrollX, scrollY, velocityX, velocityY, 0, rangeX, 0, rangeY); mDelegate.invalidate(); }
public static void startScroll( Object paramObject, int paramInt1, int paramInt2, int paramInt3, int paramInt4, int paramInt5) { ((OverScroller) paramObject).startScroll(paramInt1, paramInt2, paramInt3, paramInt4, paramInt5); }
// Called immediately before the draw to update the scroll offset. public void computeScrollAndAbsorbGlow(OverScrollGlow overScrollGlow) { final boolean stillAnimating = mScroller.computeScrollOffset(); if (!stillAnimating) return; final int oldX = mDelegate.getContainerViewScrollX(); final int oldY = mDelegate.getContainerViewScrollY(); int x = mScroller.getCurrX(); int y = mScroller.getCurrY(); int rangeX = computeMaximumHorizontalScrollOffset(); int rangeY = computeMaximumVerticalScrollOffset(); if (overScrollGlow != null) { overScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY, mScroller.getCurrVelocity()); } // The mScroller is configured not to go outside of the scrollable range, so this call // should never result in attempting to scroll outside of the scrollable region. scrollBy(x - oldX, y - oldY); mDelegate.invalidate(); }
@Override public boolean onTouchEvent(MotionEvent event) { initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(event); float currentTouchY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (!mOverScroller.isFinished()) { mOverScroller.abortAnimation(); } mLastTouchY = currentTouchY; break; case MotionEvent.ACTION_MOVE: float differentY = currentTouchY - mLastTouchY; mLastTouchY = currentTouchY; if (Math.abs(differentY) > 0) { scrollBy(0, (int) -differentY); } break; case MotionEvent.ACTION_CANCEL: recycleVelocityTracker(); if (!mOverScroller.isFinished()) { mOverScroller.abortAnimation(); } break; case MotionEvent.ACTION_UP: mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) mVelocityTracker.getYVelocity(); if ((Math.abs(initialVelocity) > mMinimumVelocity)) { fling(-initialVelocity); } recycleVelocityTracker(); break; } return true; }
public void fling(int velocityX) { if (getChildCount() > 0) { int width = getWidth() - getPaddingRight() - getPaddingLeft(); int right = getChildAt(0).getWidth(); if (DEBUG) { Log.d(TAG, "fling -> velocityX = " + velocityX); Log.d(TAG, "fling -> getScrollX() = " + getScrollX()); } mScroller.fling( getScrollX(), getScrollY(), velocityX, 0, 0, Math.max(0, right - width), 0, 0, width / 2, 0); int finalX = mScroller.getFinalX(); int overX = 0; if (finalX <= 0 || finalX >= scrollPositionOfMostRecent()) { overX = width / 2; } finalX = getScrollXFromFinalX(finalX); if (DEBUG) { Log.d(TAG, "fling -> finalX = " + finalX); } mScroller.startScroll( getScrollX(), getScrollY(), finalX - getScrollX(), 0, getScrollTime(finalX)); final boolean movingRight = velocityX > 0; postInvalidateOnAnimation(); } }
@Override protected void _startUsingVelocity(int initialX, int velocity) { mScroller.fling( initialX, 0, velocity, 0, mParent.getMinX(), mParent.getMaxX(), 0, Integer.MAX_VALUE, 10, 0); }
@Override public void fling( int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY, int overX, int overY) { mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY); }
public void fling( int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) { if (isPreGingerbread) { scroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY); } else { overScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY); } }
public void fling( int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY, int overX, int overY) { if (isOld) { ((Scroller) scroller).fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY); } else { ((OverScroller) scroller) .fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY); } }
@Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { mScroller.fling( mRect.centerX(), mRect.centerY(), Math.round(velocityX), Math.round(velocityY), 0, getWidth() - SIZE, 0, getHeight() - SIZE, SIZE / 2, SIZE / 2); ViewCompat.postInvalidateOnAnimation(ScrollerView.this); return true; }
private boolean interceptTouchEvent(MotionEvent ev) { /* * This method JUST determines whether we want to intercept the motion. If we * return true, onMotionEvent will be called and we do the actual scrolling there. */ /* * Shortcut the most recurring case: the user is in the dragging state and he is * moving his finger. We want to intercept this motion. */ final int action = ev.getAction(); if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) { return true; } switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_MOVE: { /* * mIsBeingDragged == false, otherwise the shortcut would have caught it. * Check whether the user has moved far enough from his original down touch. */ /* * Locally do absolute value. mLastMotionX is set to the x value of the down * event. */ final int activePointerId = mActivePointerId; if (activePointerId == INVALID_POINTER) { // If we don't have a valid id, the touch down wasn't on content. break; } final int pointerIndex = ev.findPointerIndex(activePointerId); if (pointerIndex == -1) { Log.e(TAG, "Invalid pointerId=" + activePointerId + " in onInterceptTouchEvent"); break; } final int x = (int) ev.getX(pointerIndex); final int xDiff = (int) Math.abs(x - mLastMotionX); if (xDiff > mTouchSlop) { setHorizontalScrollBarEnabled(true); mIsBeingDragged = true; mLastMotionX = x; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); if (getParent() != null) getParent().requestDisallowInterceptTouchEvent(true); } break; } case MotionEvent.ACTION_DOWN: { final int x = (int) ev.getX(); if (!inChild((int) x, (int) ev.getY())) { mIsBeingDragged = false; recycleVelocityTracker(); break; } /* * Remember location of down touch. ACTION_DOWN always refers to pointer index * 0. */ mLastMotionX = x; mActivePointerId = ev.getPointerId(0); initOrResetVelocityTracker(); mVelocityTracker.addMovement(ev); /* * If being flinged and user touches the screen, initiate drag; otherwise * don't. mScroller.isFinished should be false when being flinged. */ mIsBeingDragged = false; break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: /* Release the drag */ mIsBeingDragged = false; mActivePointerId = INVALID_POINTER; if (mScroller.springBack(getScrollX(), getScrollY(), 0, getScrollRange(), 0, 0)) { postInvalidateOnAnimation(); } break; case MotionEvent.ACTION_POINTER_DOWN: { final int index = ev.getActionIndex(); mLastMotionX = (int) ev.getX(index); mActivePointerId = ev.getPointerId(index); break; } case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); mLastMotionX = (int) ev.getX(ev.findPointerIndex(mActivePointerId)); break; } /* * The only time we want to intercept motion events is if we are in the drag mode. */ return mIsBeingDragged; }
@Override public boolean isFinished() { return mScroller.isFinished(); }
@Override public int getCurrY() { return mScroller.getCurrY(); }
public void fling(int velocityY) { mOverScroller.fling(0, getScrollY(), 0, velocityY, 0, 0, 0, getHeaderViewHeight()); invalidate(); }
private boolean touchEvent(MotionEvent ev) { initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0 || !inScrollArea(ev)) { return false; } if ((mIsBeingDragged = !mScroller.isFinished())) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } } /* * If being flinged and user touches, stop the fling. isFinished will be false * if being flinged. */ if (!mScroller.isFinished()) { mScroller.abortAnimation(); } // Remember where the motion event started mLastMotionX = (int) ev.getX(); mActivePointerId = ev.getPointerId(0); break; } case MotionEvent.ACTION_MOVE: final int activePointerIndex = ev.findPointerIndex(mActivePointerId); if (activePointerIndex == -1) { Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent"); break; } final int x = (int) ev.getX(activePointerIndex); int deltaX = mLastMotionX - x; if (!mIsBeingDragged && Math.abs(deltaX) > mTouchSlop) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } mIsBeingDragged = true; if (deltaX > 0) { deltaX -= mTouchSlop; } else { deltaX += mTouchSlop; } } if (mIsBeingDragged) { // Scroll to follow the motion event mLastMotionX = x; final int oldX = getScrollX(); final int oldY = getScrollY(); final int range = getScrollRange(); final int overscrollMode = getOverScrollMode(); final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); if (overScrollBy(deltaX, 0, getScrollX(), 0, range, 0, mOverscrollDistance, 0, true)) { // Break our velocity if we hit a scroll barrier. mVelocityTracker.clear(); } onScrollChanged(getScrollX(), getScrollY(), oldX, oldY); } break; case MotionEvent.ACTION_UP: if (mIsBeingDragged) { final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId); if (getChildCount() > 0) { if ((Math.abs(initialVelocity) > mMinimumVelocity)) { fling(-initialVelocity); } else { int finalX = getScrollX(); finalX = getScrollXFromFinalX(finalX); if (mScroller.springBack(getScrollX(), getScrollY(), finalX, finalX, 0, 0)) { postInvalidateOnAnimation(); } } } mActivePointerId = INVALID_POINTER; mIsBeingDragged = false; recycleVelocityTracker(); } break; case MotionEvent.ACTION_CANCEL: if (mIsBeingDragged && getChildCount() > 0) { if (mScroller.springBack(getScrollX(), getScrollY(), 0, getScrollRange(), 0, 0)) { postInvalidateOnAnimation(); } mActivePointerId = INVALID_POINTER; mIsBeingDragged = false; recycleVelocityTracker(); } break; case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; } return true; }