List of usage examples for android.view MotionEvent findPointerIndex
public final int findPointerIndex(int pointerId)
From source file:android.support.design.widget.HeaderBehavior.java
@Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent ev) { if (mTouchSlop < 0) { mTouchSlop = ViewConfiguration.get(parent.getContext()).getScaledTouchSlop(); }//w w w . jav a2s. com final int action = ev.getAction(); // Shortcut since we're being dragged if (action == MotionEvent.ACTION_MOVE && mIsBeingDragged) { return true; } switch (MotionEventCompat.getActionMasked(ev)) { case MotionEvent.ACTION_DOWN: { mIsBeingDragged = false; final int x = (int) ev.getX(); final int y = (int) ev.getY(); if (canDragView(child) && parent.isPointInChildBounds(child, x, y)) { mLastMotionY = y; mActivePointerId = ev.getPointerId(0); ensureVelocityTracker(); } break; } case MotionEvent.ACTION_MOVE: { 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) { break; } final int y = (int) ev.getY(pointerIndex); final int yDiff = Math.abs(y - mLastMotionY); if (yDiff > mTouchSlop) { mIsBeingDragged = true; mLastMotionY = y; } break; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: { mIsBeingDragged = false; mActivePointerId = INVALID_POINTER; if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } break; } } if (mVelocityTracker != null) { mVelocityTracker.addMovement(ev); } return mIsBeingDragged; }
From source file:com.lovejjfg.powerrefresh.PowerRefreshLayout.java
@Override public boolean onTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); int pointerIndex; if (!isEnabled() || !canChildScrollUp() || isLoading || isRefreshing || mNestedScrollInProgress) { // Fail fast if we're not in a state where a swipe is possible return false; }// w w w. j a va2s .c om switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = ev.getPointerId(0); mIsBeingDragged = false; break; case MotionEvent.ACTION_MOVE: { pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { return false; } final float y = ev.getY(pointerIndex); startDragging(y); //in this case ,just can refresh. if (mIsBeingDragged) { final float overscrollTop = (y - mInitialMotionY); if (overscrollTop < 0 && getScrollY() > 0) { ev.setAction(MotionEvent.ACTION_CANCEL); return false; } currentStatus = STATE_REFRESH; goToRefresh((int) overscrollTop); } mInitialMotionY = y; break; } case MotionEventCompat.ACTION_POINTER_DOWN: { pointerIndex = MotionEventCompat.getActionIndex(ev); if (pointerIndex < 0) { return false; } mActivePointerId = ev.getPointerId(pointerIndex); break; } // case MotionEventCompat.ACTION_POINTER_UP: // onSecondaryPointerUp(ev); // break; case MotionEvent.ACTION_UP: { pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { return false; } if (mIsBeingDragged) { mIsBeingDragged = false; resetScroll(); } mActivePointerId = INVALID_POINTER; return false; } case MotionEvent.ACTION_CANCEL: resetScroll(); return false; } return true; }
From source file:com.shizhefei.view.coolrefreshview.CoolRefreshView.java
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); int pointerIndex; if (!isEnabled() || canChildScrollUp() || mRefreshing || mNestedScrollInProgress) { // Fail fast if we're not in a state where a swipe is possible return false; }//from w ww. java 2s.c o m switch (action) { case MotionEvent.ACTION_DOWN: // setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true); mActivePointerId = ev.getPointerId(0); mIsBeingDragged = false; pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { return false; } mInitialDownY = ev.getY(pointerIndex); mLastMotionY = getMotionEventY(ev, pointerIndex); break; case MotionEvent.ACTION_MOVE: if (mActivePointerId == INVALID_POINTER) { Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id."); return false; } pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { return false; } final float y = ev.getY(pointerIndex); startDragging(y); break; case MotionEventCompat.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mIsBeingDragged = false; mActivePointerId = INVALID_POINTER; break; } return mIsBeingDragged; }
From source file:com.klinker.deskclock.widget.multiwaveview.GlowPadView.java
private void handleMove(MotionEvent event) { int activeTarget = -1; final int historySize = event.getHistorySize(); ArrayList<TargetDrawable> targets = mTargetDrawables; int ntargets = targets.size(); float x = 0.0f; float y = 0.0f; int actionIndex = event.findPointerIndex(mPointerId); if (actionIndex == -1) { return; // no data for this pointer }//from ww w .j av a 2 s . com for (int k = 0; k < historySize + 1; k++) { float eventX = k < historySize ? event.getHistoricalX(actionIndex, k) : event.getX(actionIndex); float eventY = k < historySize ? event.getHistoricalY(actionIndex, k) : event.getY(actionIndex); // tx and ty are relative to wave center float tx = eventX - mWaveCenterX; float ty = eventY - mWaveCenterY; float touchRadius = (float) Math.sqrt(dist2(tx, ty)); final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f; float limitX = tx * scale; float limitY = ty * scale; double angleRad = Math.atan2(-ty, tx); if (!mDragging) { trySwitchToFirstTouchState(eventX, eventY); } if (mDragging) { // For multiple targets, snap to the one that matches final float snapRadius = mOuterRadius - mSnapMargin; final float snapDistance2 = snapRadius * snapRadius; // Find first target in range for (int i = 0; i < ntargets; i++) { TargetDrawable target = targets.get(i); double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets; double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets; if (target.isEnabled()) { boolean angleMatches = (angleRad > targetMinRad && angleRad <= targetMaxRad) || (angleRad + 2 * Math.PI > targetMinRad && angleRad + 2 * Math.PI <= targetMaxRad); if (angleMatches && (dist2(tx, ty) > snapDistance2)) { activeTarget = i; } } } } x = limitX; y = limitY; } if (!mDragging) { return; } if (activeTarget != -1) { switchToState(STATE_SNAP, x, y); updateGlowPosition(x, y); } else { switchToState(STATE_TRACKING, x, y); updateGlowPosition(x, y); } if (mActiveTarget != activeTarget) { // Defocus the old target if (mActiveTarget != -1) { TargetDrawable target = targets.get(mActiveTarget); target.setState(TargetDrawable.STATE_INACTIVE); } // Focus the new target if (activeTarget != -1) { TargetDrawable target = targets.get(activeTarget); target.setState(TargetDrawable.STATE_FOCUSED); final AccessibilityManager accessibilityManager = (AccessibilityManager) getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); if (accessibilityManager.isEnabled()) { String targetContentDescription = getTargetDescription(activeTarget); if (Build.VERSION.SDK_INT >= 16) { announceForAccessibility(targetContentDescription); } else { AccessibilityEvent acc_event = AccessibilityEvent .obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); AccessibilityRecordCompat arc = new AccessibilityRecordCompat(acc_event); arc.setSource(this); acc_event.setClassName(this.getClass().getName()); acc_event.setPackageName(this.getContext().getPackageName()); acc_event.setEnabled(this.isEnabled()); acc_event.getText().add(targetContentDescription); accessibilityManager.sendAccessibilityEvent(acc_event); } } } } mActiveTarget = activeTarget; }
From source file:com.shizhefei.view.coolrefreshview.CoolRefreshView.java
@Override public boolean onTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); int pointerIndex = -1; if (!isEnabled() || canChildScrollUp() || mRefreshing || mNestedScrollInProgress) { // Fail fast if we're not in a state where a swipe is possible return false; }/*from w w w. ja v a2 s . c o m*/ switch (action) { case MotionEvent.ACTION_DOWN: mActivePointerId = ev.getPointerId(0); mIsBeingDragged = false; mLastMotionY = getMotionEventY(ev, mActivePointerId); break; case MotionEvent.ACTION_MOVE: { pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id."); return false; } final float y = ev.getY(pointerIndex); startDragging(y); if (mIsBeingDragged) { float dy = mLastMotionY - y; touchMove((int) dy); mLastMotionY = y; } break; } case MotionEventCompat.ACTION_POINTER_DOWN: { pointerIndex = MotionEventCompat.getActionIndex(ev); if (pointerIndex < 0) { Log.e(LOG_TAG, "Got ACTION_POINTER_DOWN event but have an invalid action index."); return false; } mActivePointerId = ev.getPointerId(pointerIndex); break; } case MotionEventCompat.ACTION_POINTER_UP: onSecondaryPointerUp(ev); break; case MotionEvent.ACTION_UP: { pointerIndex = ev.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { Log.e(LOG_TAG, "Got ACTION_UP event but don't have an active pointer id."); return false; } if (mIsBeingDragged) { // final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE; mIsBeingDragged = false; finishSpinner(); } mActivePointerId = INVALID_POINTER; return false; } case MotionEvent.ACTION_CANCEL: return false; } return true; }
From source file:com.gu.swiperefresh.SwipeRefreshPlush.java
@Override public boolean onTouchEvent(MotionEvent event) { final int action = MotionEventCompat.getActionMasked(event); int pointerIndex; if (mReturningToStart && action == MotionEvent.ACTION_DOWN) { mReturningToStart = false;/* w w w. j av a2 s. com*/ } if (!isEnabled() || mReturningToStart || mRefreshController.isRefresh() || mNestedScrollInProgress) { // Fail fast if we're not in a state where a swipe is possible return false; } switch (action) { case MotionEvent.ACTION_DOWN: mIsBeingDragUp = false; mIsBeingDragDown = false; mActivePointerId = event.getPointerId(0); pointerIndex = event.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { return false; } mInitialDownY = event.getY(pointerIndex); mLastY = mInitialDownY; return false; case MotionEvent.ACTION_CANCEL: return false; case MotionEvent.ACTION_MOVE: { pointerIndex = event.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { // Log.e(LOG_TAG, "Got ACTION_MOVE event but have an invalid active pointer id."); return false; } final float y = event.getY(pointerIndex); startDragging(y); if (mIsBeingDragUp) { final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE; if (overscrollTop > 0) { mRefreshController.showPullRefresh(overscrollTop); } } else if (mIsBeingDragDown) { int dy = (int) (y - mLastY); Log.i(TAG, "lasty:" + mLastY); Log.i(TAG, "dy:" + dy); // if (dy >= 0.5) { hideLoadMoreView(Math.abs(dy)); } else if (dy < -0.5) { showLoadMoreView(Math.abs(dy)); } } mLastY = y; break; } case MotionEvent.ACTION_UP: { pointerIndex = event.findPointerIndex(mActivePointerId); if (pointerIndex < 0) { // Log.e(LOG_TAG, "Got ACTION_UP event but don't have an active pointer id."); return false; } if (mIsBeingDragUp) { final float y = event.getY(pointerIndex); final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE; mIsBeingDragUp = false; if (overscrollTop > 0) mRefreshController.finishPullRefresh(overscrollTop); } if (mIsBeingDragDown) { final float y = event.getY(pointerIndex); final float overscrollBottom = (y - mInitialMotionY); mIsBeingDragDown = false; if (overscrollBottom < 0) mLoadViewController.finishPullRefresh(Math.abs(overscrollBottom)); } mActivePointerId = INVALID_POINTER; return false; } } return true; }
From source file:com.tasomaniac.openwith.resolver.ResolverDrawerLayout.java
@Override public boolean onTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); mVelocityTracker.addMovement(ev);//www .j a va2s . c om boolean handled = false; switch (action) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(0); final float y = ev.getY(0); mInitialTouchX = x; mInitialTouchY = mLastTouchY = y; mActivePointerId = ev.getPointerId(0); final boolean hitView = findChildUnder(mInitialTouchX, mInitialTouchY) != null; handled = (!hitView && mOnDismissedListener != null) || mCollapsibleHeight > 0; mIsDragging = hitView && handled; abortAnimation(); } break; case MotionEvent.ACTION_MOVE: { int index = ev.findPointerIndex(mActivePointerId); if (index < 0) { Timber.e("Bad pointer id %d, resetting", mActivePointerId); index = 0; mActivePointerId = ev.getPointerId(0); mInitialTouchX = ev.getX(0); mInitialTouchY = mLastTouchY = ev.getY(0); } final float x = ev.getX(index); final float y = ev.getY(index); if (!mIsDragging) { final float dy = y - mInitialTouchY; if (Math.abs(dy) > mTouchSlop && findChildUnder(x, y) != null) { handled = mIsDragging = true; mLastTouchY = Math.max(mLastTouchY - mTouchSlop, Math.min(mLastTouchY + dy, mLastTouchY + mTouchSlop)); } } if (mIsDragging) { final float dy = y - mLastTouchY; performDrag(dy); } mLastTouchY = y; } break; case MotionEvent.ACTION_POINTER_DOWN: { final int pointerIndex = MotionEventCompat.getActionIndex(ev); mActivePointerId = ev.getPointerId(pointerIndex); mInitialTouchX = ev.getX(pointerIndex); mInitialTouchY = mLastTouchY = ev.getY(pointerIndex); } break; case MotionEvent.ACTION_POINTER_UP: { onSecondaryPointerUp(ev); } break; case MotionEvent.ACTION_UP: { final boolean wasDragging = mIsDragging; mIsDragging = false; if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null && findChildUnder(ev.getX(0), ev.getY(0)) == null) { if (mOnDismissedListener != null) { dispatchOnDismissed(); resetTouch(); return true; } } if (mOpenOnClick && Math.abs(ev.getX(0) - mInitialTouchX) < mTouchSlop && Math.abs(ev.getY(0) - mInitialTouchY) < mTouchSlop) { smoothScrollTo(0, 0); return true; } mVelocityTracker.computeCurrentVelocity(1000); final float yvel = VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { if (mOnDismissedListener != null && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); mDismissOnScrollerFinished = true; } else { smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); } } else { smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); } resetTouch(); } break; case MotionEvent.ACTION_CANCEL: { if (mIsDragging) { smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); } resetTouch(); return true; } } return handled; }
From source file:study.com.s_sxl.carelib.pullRefreshView.layout.FlingLayout.java
/******************************************************************/ @Override/*from w w w.ja v a2 s. c om*/ public boolean dispatchTouchEvent(MotionEvent ev) { if (mPullView != null && !ViewCompat.isNestedScrollingEnabled(mPullView)) { float moveY = getMoveY(); int pointerCount = ev.getPointerCount(); int pointerIndex = ev.getActionIndex(); if (!mScroller.isFinished()) { mScroller.abortAnimation(); } switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: mPointerId = ev.getPointerId(pointerIndex); float x = ev.getX(pointerIndex); float y = ev.getY(pointerIndex); tempY = downY = y; tempX = downX = x; tempStateType = SCROLL_STATE_TOUCH_SCROLL; if (moveY != 0) { return true; } break; case MotionEvent.ACTION_POINTER_DOWN: mPointerId = ev.getPointerId(pointerIndex); tempX = ev.getX(pointerIndex); tempY = ev.getY(pointerIndex); break; case MotionEvent.ACTION_MOVE: pointerIndex = ev.findPointerIndex(mPointerId); float mx; float my; if (pointerCount > pointerIndex && pointerIndex >= 0) { mx = ev.getX(pointerIndex); my = ev.getY(pointerIndex); } else { mx = ev.getX(); my = ev.getY(); } //????? int dataX = (int) (mx - tempX); int dataY = (int) (my - tempY); tempX = mx; tempY = my; if (isScrolling || (Math.abs(dataY) > Math.abs(dataX))) { isScrolling = true; if (moveY == 0) { // 0,0 //?? if ((dataY < 0 && canPullUp()) || (dataY > 0 && canPullDown())) { moveBy(dataY); return true; } } else { //?0,0 ev.setAction(MotionEvent.ACTION_CANCEL);//? if ((moveY < 0 && moveY + dataY >= 0) || (moveY > 0 && moveY + dataY <= 0)) { //0,0 ev.setAction(MotionEvent.ACTION_DOWN); moveTo(0); } else if ((moveY > 0 && dataY > 0) || (moveY < 0 && dataY < 0)) { //?? if (maxDistance == 0 || Math.abs(moveY) < maxDistance) { int ps = 0; int hDataY = dataY / 2; if (maxDistance == 0) { ps = (int) (-hDataY * Math.abs(moveY) / (float) MAXDISTANCE) - hDataY; } else { ps = (int) (-hDataY * Math.abs(moveY) / (float) maxDistance) - hDataY; } moveBy(ps + dataY); } else if (moveY > maxDistance) { moveTo(maxDistance); } else if (moveY < -maxDistance) { moveTo(-maxDistance); } } else { moveBy(dataY); } } } else { ev.setLocation(mx, downY); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: startFling(); isScrolling = false; break; case MotionEvent.ACTION_POINTER_UP: // ?? int pointerIdLeave = ev.getPointerId(pointerIndex); if (mPointerId == pointerIdLeave) { // ??????VelocityTracker int reIndex = pointerIndex == 0 ? 1 : 0; mPointerId = ev.getPointerId(reIndex); // ? tempY = ev.getY(reIndex); } } return super.dispatchTouchEvent(ev) || isScrolling; } else { return super.dispatchTouchEvent(ev); } }
From source file:com.leap.mini.widget.pullrefresh.base.layout.FlingLayout.java
/******************************************************************/ @Override//from w w w . j ava2s . c o m public boolean dispatchTouchEvent(MotionEvent ev) { if (mPullView != null && !ViewCompat.isNestedScrollingEnabled(mPullView)) { float moveY = getMoveY(); int pointerCount = ev.getPointerCount(); int pointerIndex = ev.getActionIndex(); if (!mScroller.isFinished()) { mScroller.abortAnimation(); } switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: mPointerId = ev.getPointerId(pointerIndex); float x = ev.getX(pointerIndex); float y = ev.getY(pointerIndex); tepmY = downY = y; tepmX = downX = x; tempStateType = SCROLL_STATE_TOUCH_SCROLL; if (moveY != 0) { return true; } break; case MotionEvent.ACTION_POINTER_DOWN: mPointerId = ev.getPointerId(pointerIndex); tepmX = ev.getX(pointerIndex); tepmY = ev.getY(pointerIndex); break; case MotionEvent.ACTION_MOVE: pointerIndex = ev.findPointerIndex(mPointerId); float mx; float my; if (pointerCount > pointerIndex && pointerIndex >= 0) { mx = ev.getX(pointerIndex); my = ev.getY(pointerIndex); } else { mx = ev.getX(); my = ev.getY(); } // ????? int dataX = (int) (mx - tepmX); int dataY = (int) (my - tepmY); tepmX = mx; tepmY = my; if (isScrolling || (Math.abs(dataY) > Math.abs(dataX))) { isScrolling = true; if (moveY == 0) { // 0,0 // ?? if ((dataY < 0 && canPullUp()) || (dataY > 0 && canPullDown())) { moveBy(dataY); return true; } } else { // ?0,0 ev.setAction(MotionEvent.ACTION_CANCEL);// ? if ((moveY < 0 && moveY + dataY >= 0) || (moveY > 0 && moveY + dataY <= 0)) { // 0,0 ev.setAction(MotionEvent.ACTION_DOWN); moveTo(0); } else if ((moveY > 0 && dataY > 0) || (moveY < 0 && dataY < 0)) { // ?? if (maxDistance == 0 || Math.abs(moveY) < maxDistance) { int ps = 0; int hDataY = dataY / 2; if (maxDistance == 0) { ps = (int) (-hDataY * Math.abs(moveY) / (float) MAXDISTANCE) - hDataY; } else { ps = (int) (-hDataY * Math.abs(moveY) / (float) maxDistance) - hDataY; } moveBy(ps + dataY); } else if (moveY > maxDistance) { moveTo(maxDistance); } else if (moveY < -maxDistance) { moveTo(-maxDistance); } } else { moveBy(dataY); } } } else { ev.setLocation(mx, downY); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: startFling(); isScrolling = false; break; case MotionEvent.ACTION_POINTER_UP: // ?? int pointerIdLeave = ev.getPointerId(pointerIndex); if (mPointerId == pointerIdLeave) { // ??????VelocityTracker int reIndex = pointerIndex == 0 ? 1 : 0; mPointerId = ev.getPointerId(reIndex); // ? tepmY = ev.getY(reIndex); } } return super.dispatchTouchEvent(ev) || isScrolling; } else { return super.dispatchTouchEvent(ev); } }
From source file:com.ybao.pullrefreshview.layout.FlingLayout.java
/******************************************************************/ @Override/* ww w . ja va 2s . co m*/ public boolean dispatchTouchEvent(MotionEvent ev) { if (mPullView != null && !ViewCompat.isNestedScrollingEnabled(mPullView)) { float moveY = getMoveY(); int pointerCount = ev.getPointerCount(); int pointerIndex = ev.getActionIndex(); if (!mScroller.isFinished()) { mScroller.abortAnimation(); } switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: mPointerId = ev.getPointerId(pointerIndex); float x = ev.getX(pointerIndex); float y = ev.getY(pointerIndex); tepmY = downY = y; tepmX = downX = x; tempStateType = SCROLL_STATE_TOUCH_SCROLL; if (moveY != 0) { return true; } break; case MotionEvent.ACTION_POINTER_DOWN: mPointerId = ev.getPointerId(pointerIndex); tepmX = ev.getX(pointerIndex); tepmY = ev.getY(pointerIndex); break; case MotionEvent.ACTION_MOVE: pointerIndex = ev.findPointerIndex(mPointerId); float mx; float my; if (pointerCount > pointerIndex && pointerIndex >= 0) { mx = ev.getX(pointerIndex); my = ev.getY(pointerIndex); } else { mx = ev.getX(); my = ev.getY(); } //????? int dataX = (int) (mx - tepmX); int dataY = (int) (my - tepmY); tepmX = mx; tepmY = my; if (isScrolling || (Math.abs(dataY) > Math.abs(dataX))) { isScrolling = true; if (moveY == 0) { // 0,0 //?? if ((dataY < 0 && canPullUp()) || (dataY > 0 && canPullDown())) { moveBy(dataY); return true; } } else { //?0,0 ev.setAction(MotionEvent.ACTION_CANCEL);//? if ((moveY < 0 && moveY + dataY >= 0) || (moveY > 0 && moveY + dataY <= 0)) { //0,0 ev.setAction(MotionEvent.ACTION_DOWN); moveTo(0); } else if ((moveY > 0 && dataY > 0) || (moveY < 0 && dataY < 0)) { //?? if (maxDistance == 0 || Math.abs(moveY) < maxDistance) { int ps = 0; int hDataY = dataY / 2; if (maxDistance == 0) { ps = (int) (-hDataY * Math.abs(moveY) / (float) MAXDISTANCE) - hDataY; } else { ps = (int) (-hDataY * Math.abs(moveY) / (float) maxDistance) - hDataY; } moveBy(ps + dataY); } else if (moveY > maxDistance) { moveTo(maxDistance); } else if (moveY < -maxDistance) { moveTo(-maxDistance); } } else { moveBy(dataY); } } } else { ev.setLocation(mx, downY); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: startFling(); isScrolling = false; break; case MotionEvent.ACTION_POINTER_UP: // ?? int pointerIdLeave = ev.getPointerId(pointerIndex); if (mPointerId == pointerIdLeave) { // ??????VelocityTracker int reIndex = pointerIndex == 0 ? 1 : 0; mPointerId = ev.getPointerId(reIndex); // ? tepmY = ev.getY(reIndex); } } return super.dispatchTouchEvent(ev) || isScrolling; } else { return super.dispatchTouchEvent(ev); } }