コード例 #1
0
  /**
   * Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
   *
   * @param x the number of pixels to scroll by on the X axis
   * @param y the number of pixels to scroll by on the Y axis
   * @param velocity the velocity associated with a fling, if applicable. (0 otherwise)
   */
  void smoothScrollTo(int x, int y, int velocity) {
    if (getChildCount() == 0) {
      // Nothing to do.
      setScrollingCacheEnabled(false);
      return;
    }
    int sx = getScrollX();
    int sy = getScrollY();
    int dx = x - sx;
    int dy = y - sy;
    if (dx == 0 && dy == 0) {
      completeScroll();
      if (isMenuOpen()) {
        if (mOpenedListener != null) mOpenedListener.onOpened();
      } else {
        if (mClosedListener != null) mClosedListener.onClosed();
      }
      return;
    }

    setScrollingCacheEnabled(true);
    mScrolling = true;

    final int width = getBehindWidth();
    final int halfWidth = width / 2;
    final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dx) / width);
    final float distance = halfWidth + halfWidth * distanceInfluenceForSnapDuration(distanceRatio);

    int duration = 0;
    velocity = Math.abs(velocity);
    if (velocity > 0) {
      duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
    } else {
      final float pageDelta = (float) Math.abs(dx) / width;
      duration = (int) ((pageDelta + 1) * 100);
      duration = MAX_SETTLE_DURATION;
    }
    duration = Math.min(duration, MAX_SETTLE_DURATION);

    mScroller.startScroll(sx, sy, dx, dy, duration);
    invalidate();
  }
コード例 #2
0
 private void completeScroll() {
   boolean needPopulate = mScrolling;
   if (needPopulate) {
     // Done with scroll, no longer want to cache view drawing.
     setScrollingCacheEnabled(false);
     mScroller.abortAnimation();
     int oldX = getScrollX();
     int oldY = getScrollY();
     int x = mScroller.getCurrX();
     int y = mScroller.getCurrY();
     if (oldX != x || oldY != y) {
       scrollTo(x, y);
     }
     if (isMenuOpen()) {
       if (mOpenedListener != null) mOpenedListener.onOpened();
     } else {
       if (mClosedListener != null) mClosedListener.onClosed();
     }
   }
   mScrolling = false;
 }
コード例 #3
0
 private void determineDrag(MotionEvent ev) {
   final int activePointerId = mActivePointerId;
   final int pointerIndex = getPointerIndex(ev, activePointerId);
   if (activePointerId == INVALID_POINTER || pointerIndex == INVALID_POINTER) return;
   final float x = MotionEventCompat.getX(ev, pointerIndex);
   final float dx = x - mLastMotionX;
   final float xDiff = Math.abs(dx);
   final float y = MotionEventCompat.getY(ev, pointerIndex);
   final float dy = y - mLastMotionY;
   final float yDiff = Math.abs(dy);
   if (xDiff > (isMenuOpen() ? mTouchSlop / 2 : mTouchSlop)
       && xDiff > yDiff
       && thisSlideAllowed(dx)) {
     startDrag();
     mLastMotionX = x;
     mLastMotionY = y;
     setScrollingCacheEnabled(true);
     // TODO add back in touch slop check
   } else if (xDiff > mTouchSlop) {
     mIsUnableToDrag = true;
   }
 }
コード例 #4
0
  void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
    if (!always && mCurItem == item) {
      setScrollingCacheEnabled(false);
      return;
    }

    item = mViewBehind.getMenuPage(item);

    final boolean dispatchSelected = mCurItem != item;
    mCurItem = item;
    final int destX = getDestScrollX(mCurItem);
    if (dispatchSelected && mOnPageChangeListener != null) {
      mOnPageChangeListener.onPageSelected(item);
    }
    if (dispatchSelected && mInternalPageChangeListener != null) {
      mInternalPageChangeListener.onPageSelected(item);
    }
    if (smoothScroll) {
      smoothScrollTo(destX, 0, velocity);
    } else {
      completeScroll();
      scrollTo(destX, 0);
    }
  }
コード例 #5
0
  @Override
  public boolean onTouchEvent(MotionEvent ev) {

    if (!mEnabled) return false;

    if (!mIsBeingDragged && !thisTouchAllowed(ev)) return false;

    //		if (!mIsBeingDragged && !mQuickReturn)
    //			return false;

    final int action = ev.getAction();

    if (mVelocityTracker == null) {
      mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(ev);

    switch (action & MotionEventCompat.ACTION_MASK) {
      case MotionEvent.ACTION_DOWN:
        /*
         * If being flinged and user touches, stop the fling. isFinished
         * will be false if being flinged.
         */
        completeScroll();

        // Remember where the motion event started
        mLastMotionX = mInitialMotionX = ev.getX();
        mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
        break;
      case MotionEvent.ACTION_MOVE:
        if (!mIsBeingDragged) {
          if (mActivePointerId == INVALID_POINTER) break;
          final int pointerIndex = getPointerIndex(ev, mActivePointerId);
          if (pointerIndex < 0 || pointerIndex >= ev.getPointerCount()) break;
          final float x = MotionEventCompat.getX(ev, pointerIndex);
          final float dx = x - mLastMotionX;
          final float xDiff = Math.abs(dx);
          final float y = MotionEventCompat.getY(ev, pointerIndex);
          final float yDiff = Math.abs(y - mLastMotionY);
          if (DEBUG)
            Log.v(
                TAG,
                "onTouch moved to:("
                    + x
                    + ", "
                    + y
                    + "), diff:("
                    + xDiff
                    + ", "
                    + yDiff
                    + ")\nmIsBeingDragged:"
                    + mIsBeingDragged
                    + ", mLastMotionX:"
                    + mLastMotionX);
          if ((xDiff > mTouchSlop || (mQuickReturn && xDiff > mTouchSlop / 4))
              && xDiff > yDiff
              && thisSlideAllowed(dx)) {
            if (DEBUG) Log.v(TAG, "Starting drag! from onTouch");
            startDrag();
            mLastMotionX = x;
            setScrollingCacheEnabled(true);
          } else {
            if (DEBUG) Log.v(TAG, "onTouch returning false");
            return false;
          }
        }
        if (mIsBeingDragged) {
          // Scroll to follow the motion event
          final int activePointerIndex = getPointerIndex(ev, mActivePointerId);
          if (mActivePointerId == INVALID_POINTER) {
            break;
          }
          final float x = MotionEventCompat.getX(ev, activePointerIndex);
          final float deltaX = mLastMotionX - x;
          mLastMotionX = x;
          float oldScrollX = getScrollX();
          float scrollX = oldScrollX + deltaX;
          final float leftBound = getLeftBound();
          final float rightBound = getRightBound();
          if (scrollX < leftBound) {
            scrollX = leftBound;
          } else if (scrollX > rightBound) {
            scrollX = rightBound;
          }
          // Don't lose the rounded component
          mLastMotionX += scrollX - (int) scrollX;
          scrollTo((int) scrollX, getScrollY());
          pageScrolled((int) scrollX);
        }
        break;
      case MotionEvent.ACTION_UP:
        if (mIsBeingDragged) {
          final VelocityTracker velocityTracker = mVelocityTracker;
          velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
          int initialVelocity =
              (int) VelocityTrackerCompat.getXVelocity(velocityTracker, mActivePointerId);
          final int scrollX = getScrollX();
          //				final int widthWithMargin = getWidth();
          //				final float pageOffset = (float) (scrollX % widthWithMargin) / widthWithMargin;
          // TODO test this. should get better flinging behavior
          final float pageOffset = (float) (scrollX - getDestScrollX(mCurItem)) / getBehindWidth();
          final int activePointerIndex = getPointerIndex(ev, mActivePointerId);
          if (mActivePointerId != INVALID_POINTER) {
            final float x = MotionEventCompat.getX(ev, activePointerIndex);
            final int totalDelta = (int) (x - mInitialMotionX);
            int nextPage = determineTargetPage(pageOffset, initialVelocity, totalDelta);
            setCurrentItemInternal(nextPage, true, true, initialVelocity);
          } else {
            setCurrentItemInternal(mCurItem, true, true, initialVelocity);
          }
          mActivePointerId = INVALID_POINTER;
          endDrag();
        } else if (mQuickReturn
            && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
          // close the menu
          setCurrentItem(1);
          endDrag();
        }
        break;
      case MotionEvent.ACTION_CANCEL:
        if (mIsBeingDragged) {
          setCurrentItemInternal(mCurItem, true, true);
          mActivePointerId = INVALID_POINTER;
          endDrag();
        }
        break;
      case MotionEventCompat.ACTION_POINTER_DOWN:
        {
          final int index = MotionEventCompat.getActionIndex(ev);
          final float x = MotionEventCompat.getX(ev, index);
          mLastMotionX = x;
          mActivePointerId = MotionEventCompat.getPointerId(ev, index);
          break;
        }
      case MotionEventCompat.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        int pointerIndex = this.getPointerIndex(ev, mActivePointerId);
        if (mActivePointerId == INVALID_POINTER) break;
        mLastMotionX = MotionEventCompat.getX(ev, pointerIndex);
        break;
    }
    return true;
  }
コード例 #6
0
  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {

    if (!mEnabled) return false;

    final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;

    if (DEBUG) if (action == MotionEvent.ACTION_DOWN) Log.v(TAG, "Received ACTION_DOWN");

    if (action == MotionEvent.ACTION_CANCEL
        || action == MotionEvent.ACTION_UP
        || (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {
      endDrag();
      return false;
    }

    switch (action) {
      case MotionEvent.ACTION_MOVE:
        final int activePointerId = mActivePointerId;
        if (activePointerId == INVALID_POINTER) break;
        final int pointerIndex = this.getPointerIndex(ev, activePointerId);
        if (pointerIndex < 0 || pointerIndex >= ev.getPointerCount()) break;
        final float x = MotionEventCompat.getX(ev, pointerIndex);
        final float dx = x - mLastMotionX;
        final float xDiff = Math.abs(dx);
        final float y = MotionEventCompat.getY(ev, pointerIndex);
        final float yDiff = Math.abs(y - mLastMotionY);
        if (DEBUG)
          Log.v(
              TAG,
              "onInterceptTouch moved to:("
                  + x
                  + ", "
                  + y
                  + "), diff:("
                  + xDiff
                  + ", "
                  + yDiff
                  + "), mLastMotionX:"
                  + mLastMotionX);
        if (xDiff > mTouchSlop && xDiff > yDiff && thisSlideAllowed(dx)) {
          if (DEBUG) Log.v(TAG, "Starting drag! from onInterceptTouch");
          startDrag();
          mLastMotionX = x;
          setScrollingCacheEnabled(true);
        } else if (yDiff > mTouchSlop) {
          mIsUnableToDrag = true;
        }
        break;

      case MotionEvent.ACTION_DOWN:
        mActivePointerId =
            ev.getAction()
                & ((Build.VERSION.SDK_INT >= 8)
                    ? MotionEvent.ACTION_POINTER_INDEX_MASK
                    : MotionEvent.ACTION_POINTER_INDEX_MASK);
        mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, mActivePointerId);
        mLastMotionY = MotionEventCompat.getY(ev, mActivePointerId);
        if (thisTouchAllowed(ev)) {
          mIsBeingDragged = false;
          mIsUnableToDrag = false;
          if (isMenuOpen()
              && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
            mQuickReturn = true;
          }
        } else {
          mIsUnableToDrag = true;
        }
        break;
      case MotionEventCompat.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;
    }

    if (!mIsBeingDragged) {
      if (mVelocityTracker == null) {
        mVelocityTracker = VelocityTracker.obtain();
      }
      mVelocityTracker.addMovement(ev);
    }
    return mIsBeingDragged || mQuickReturn;
  }