下面列出了android.view.ViewParent#requestDisallowInterceptTouchEvent ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* disables intercept touchevents
*/
public void disableScroll() {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
/**
* 是否劫持输入事件, ViewPager
*/
@Override
public void interceptParentTouchEvent(boolean intercept)
{
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(intercept);
}
}
@Override
public void onDrag(float dx, float dy) {
if (mScaleDragDetector.isScaling()) {
return; // Do not drag if we are already scaling
}
if (DEBUG) {
LogManager.getLogger().d(LOG_TAG,
String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy));
}
ImageView imageView = getImageView();
mSuppMatrix.postTranslate(dx, dy);
checkAndDisplayMatrix();
/**
* Here we decide whether to let the ImageView's parent to start taking
* over the touch event.
*
* First we check whether this function is enabled. We never want the
* parent to take over if we're scaling. We then check the edge we're
* on, and the direction of the scroll (i.e. if we're pulling against
* the edge, aka 'overscrolling', let the parent take over).
*/
ViewParent parent = imageView.getParent();
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) {
if (mScrollEdge == EDGE_BOTH
|| (mScrollEdge == EDGE_LEFT && dx >= 1f)
|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
if (null != parent)
parent.requestDisallowInterceptTouchEvent(false);
}
} else {
if (null != parent) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
}
@Override
public void onDrag(float dx, float dy) {
if (mScaleDragDetector.isScaling()) {
return; // Do not drag if we are already scaling
}
if (mOnViewDragListener != null) {
mOnViewDragListener.onDrag(dx, dy);
}
mSuppMatrix.postTranslate(dx, dy);
checkAndDisplayMatrix();
/*
* Here we decide whether to let the ImageView's parent to start taking
* over the touch event.
*
* First we check whether this function is enabled. We never want the
* parent to take over if we're scaling. We then check the edge we're
* on, and the direction of the scroll (i.e. if we're pulling against
* the edge, aka 'overscrolling', let the parent take over).
*/
ViewParent parent = mImageView.getParent();
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) {
if (mScrollEdge == EDGE_BOTH
|| (mScrollEdge == EDGE_LEFT && dx >= 1f)
|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
}
} else {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
}
private boolean startScrollIfNeeded( int x ) {
// Check if we have moved far enough that it looks more like a
// scroll than a tap
final int deltaX = x - mMotionX;
final int distance = Math.abs( deltaX );
final boolean overscroll = getScrollX() != 0;
if ( overscroll || distance > mTouchSlop ) {
createScrollingCache();
if ( overscroll ) {
mTouchMode = TOUCH_MODE_OVERSCROLL;
mMotionCorrection = 0;
} else {
mTouchMode = TOUCH_MODE_SCROLL;
mMotionCorrection = deltaX > 0 ? mTouchSlop : -mTouchSlop;
}
final Handler handler = getHandler();
// Handler should not be null unless the AbsListView is not attached to a
// window, which would make it very hard to scroll it... but the monkeys
// say it's possible.
if ( handler != null ) {
handler.removeCallbacks( mPendingCheckForLongPress );
}
setPressed( false );
View motionView = getChildAt( mMotionPosition - mFirstPosition );
if ( motionView != null ) {
motionView.setPressed( false );
}
reportScrollStateChange( OnScrollListener.SCROLL_STATE_TOUCH_SCROLL );
// Time to start stealing events! Once we've stolen them, don't let anyone
// steal from us
final ViewParent parent = getParent();
if ( parent != null ) {
parent.requestDisallowInterceptTouchEvent( true );
}
scrollIfNeeded( x );
return true;
}
return false;
}
@Override
public void onDrag(float dx, float dy) {
if (mScaleDragDetector.isScaling()) {
return; // Do not drag if we are already scaling
}
if (DEBUG) {
LogManager.getLogger().d(LOG_TAG,
String.format("onDrag: dx: %.2f. dy: %.2f", dx, dy));
}
ImageView imageView = getImageView();
mSuppMatrix.postTranslate(dx, dy);
checkAndDisplayMatrix();
/**
* Here we decide whether to let the ImageView's parent to start taking
* over the touch event.
*
* First we check whether this function is enabled. We never want the
* parent to take over if we're scaling. We then check the edge we're
* on, and the direction of the scroll (i.e. if we're pulling against
* the edge, aka 'overscrolling', let the parent take over).
*/
ViewParent parent = imageView.getParent();
if (mAllowParentInterceptOnEdge && !mScaleDragDetector.isScaling() && !mBlockParentIntercept) {
if (mScrollEdge == EDGE_BOTH
|| (mScrollEdge == EDGE_LEFT && dx >= 1f)
|| (mScrollEdge == EDGE_RIGHT && dx <= -1f)) {
if (null != parent) {
parent.requestDisallowInterceptTouchEvent(false);
}
}
} else {
if (null != parent) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
}
private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) {
final ViewParent parent = mSwipeView.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
private void attemptClaimDrag() {
ViewParent p = getParent();
if (p != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) {
final ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
super.onTouchEvent(event);
ViewParent parent = getParent();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
if (event.getX() >= 0 && event.getX() <= getWidth() &&
event.getY() >= 0 && event.getY() <= getHeight()) {
mCoordinateX = getCoordinateX(event);
}
}
break;
case MotionEvent.ACTION_MOVE: {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
mState = StateDragging;
if (event.getX() >= 0 && event.getX() <= getWidth() &&
event.getY() >= 0 && event.getY() <= getHeight()) {
mCoordinateX = getCoordinateX(event);
Log.v("EventX", event.getX() + ":" + mCoordinateX);
invalidate();
}
}
break;
case MotionEvent.ACTION_UP: {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
calculateProgress();
mState = StateNormal;
invalidate();
}
break;
case MotionEvent.ACTION_CANCEL: {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(false);
}
calculateProgress();
mState = StateNormal;
invalidate();
}
break;
}
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
final ViewParent parent = getParent();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//scroller 向右为负,向左为正
int offset;
if (isVerticalMove()){
offset = (int) (mMovePos - event.getY());
}else {
offset = (int) (mMovePos - event.getX());
}
if (Math.abs(offset) > mTouchSlop){
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
int scrollPos ;
if (isVerticalMove()){
scrollPos = getScrollY();
}else{
scrollPos = getScrollX();
}
/**
* 判断边界
*/
if (scrollPos + offset <= 0) {
scrollTo(0, 0);
return true;
}
if (isVerticalMove()){
if (scrollPos +offset >= mBottomRound - mHeight){
scrollTo(0,mBottomRound - mHeight);
return true;
}
scrollBy(0, offset);
}else{
if (scrollPos +offset >= mRightBound - mWidth) {
scrollTo(mRightBound - mWidth, 0);
return true;
}
scrollBy(offset, 0);
}
isMove = true;
if (isVerticalMove()){
mMovePos = event.getY();
}else {
mMovePos = event.getX();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mVelocityTracker.computeCurrentVelocity(1000,mMaximumVelocity);
int velocityPos ;
if (isVerticalMove()){
velocityPos = (int) mVelocityTracker.getYVelocity();
}else{
velocityPos = (int) mVelocityTracker.getXVelocity();
}
if (Math.abs(velocityPos) >= mMinimumVelocity) {
if (isVerticalMove()){
mCurScrollPos = getScrollY();
mScroller.fling(0,mCurScrollPos,0,velocityPos,
0,0,0,getHeight());
}else {
mCurScrollPos = getScrollX();
mScroller.fling(mCurScrollPos, 0, velocityPos,
0, 0, getWidth(), 0, 0);
}
if (mVelocityTracker != null) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
private void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) {
final ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent ev) {
boolean handled = false;
if (mZoomEnabled && hasDrawable((ImageView) v)) {
ViewParent parent = v.getParent();
switch (ev.getAction()) {
case ACTION_DOWN:
// First, disable the Parent from intercepting the touch
// event
if (null != parent) {
parent.requestDisallowInterceptTouchEvent(true);
}
// If we're flinging, and the user presses down, cancel
// fling
cancelFling();
break;
case ACTION_CANCEL:
case ACTION_UP:
// If the user has zoomed less than min scale, zoom back
// to min scale
if (getScale() < mMinScale) {
RectF rect = getDisplayRect();
if (null != rect) {
v.post(new AnimatedZoomRunnable(getScale(), mMinScale,
rect.centerX(), rect.centerY()));
handled = true;
}
}
break;
}
// Try the Scale/Drag detector
if (null != mScaleDragDetector) {
boolean wasScaling = mScaleDragDetector.isScaling();
boolean wasDragging = mScaleDragDetector.isDragging();
handled = mScaleDragDetector.onTouchEvent(ev);
boolean didntScale = !wasScaling && !mScaleDragDetector.isScaling();
boolean didntDrag = !wasDragging && !mScaleDragDetector.isDragging();
mBlockParentIntercept = didntScale && didntDrag;
}
// Check to see if the user double tapped
if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
handled = true;
}
}
return handled;
}
/**
* Gesture priority:horizontalPan & verticalPan > pan > swipe
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
boolean result = false;
if (e1 == null || e2 == null) {
return false;
}
float dx = Math.abs(e2.getX() - e1.getX());
float dy = Math.abs(e2.getY() - e1.getY());
WXGestureType possiblePan;
if (dx > dy) {
possiblePan = HighLevelGesture.HORIZONTALPAN;
} else {
possiblePan = HighLevelGesture.VERTICALPAN;
}
if (mPendingPan == HighLevelGesture.HORIZONTALPAN || mPendingPan == HighLevelGesture.VERTICALPAN) {
//already during directional-pan
handlePanMotionEvent(e2);
result = true;
} else if (component.containsGesture(possiblePan)) {
ViewParent p;
if ((p = component.getRealView().getParent()) != null) {
p.requestDisallowInterceptTouchEvent(true);
}
if (mPendingPan != null) {
handleMotionEvent(mPendingPan, e2);//finish pan if exist
}
mPendingPan = possiblePan;
component.fireEvent(possiblePan.toString(), createFireEventParam(e2, CUR_EVENT, START));
result = true;
} else if (containsSimplePan()) {
if (panDownTime != e1.getEventTime()) {
panDownTime = e1.getEventTime();
mPendingPan = HighLevelGesture.PAN_END;
component.fireEvent(HighLevelGesture.PAN_START.toString(),
createFireEventParam(e1, CUR_EVENT, null));
} else {
component.fireEvent(HighLevelGesture.PAN_MOVE.toString(),
createFireEventParam(e2, CUR_EVENT, null));
}
result = true;
} else if (component.containsGesture(HighLevelGesture.SWIPE)) {
if (swipeDownTime != e1.getEventTime()) {
swipeDownTime = e1.getEventTime();
List<Map<String, Object>> list = createMultipleFireEventParam(e2, null);
Map<String, Object> param = list.get(list.size() - 1);
if (Math.abs(distanceX) > Math.abs(distanceY)) {
param.put(GestureInfo.DIRECTION, distanceX > 0 ? LEFT : RIGHT);
} else {
param.put(GestureInfo.DIRECTION, distanceY > 0 ? UP : DOWN);
}
component.getInstance().fireEvent(component.getDomObject().getRef(),
HighLevelGesture.SWIPE.toString(), param);
result = true;
}
}
return result;
}
/** Touch preprocessing for handling below */
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
return false;
}
// Pass through to swipe helper if we are swiping
mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
if (mInterceptedBySwipeHelper) {
return true;
}
boolean wasScrolling = mScroller.isScrolling() ||
(mScroller.mScrollAnimator != null && mScroller.mScrollAnimator.isRunning());
int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
// Save the touch down info
mInitialMotionX = mLastMotionX = (int) ev.getX();
mInitialMotionY = mLastMotionY = (int) ev.getY();
mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
mActivePointerId = ev.getPointerId(0);
mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
// Stop the current scroll if it is still flinging
mScroller.stopScroller();
mScroller.stopBoundScrollAnimation();
// Initialize the velocity tracker
initOrResetVelocityTracker();
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
// Check if the scroller is finished yet
mIsScrolling = mScroller.isScrolling();
break;
}
case MotionEvent.ACTION_MOVE: {
if (mActivePointerId == INACTIVE_POINTER_ID) break;
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
int x = (int) ev.getX(activePointerIndex);
if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
// Save the touch move info
mIsScrolling = true;
// Initialize the velocity tracker if necessary
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
mLastMotionX = x;
mLastMotionY = y;
mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
mScroller.animateBoundScroll();
// Reset the drag state and the velocity tracker
mIsScrolling = false;
mActivePointerId = INACTIVE_POINTER_ID;
mActiveTaskView = null;
mTotalPMotion = 0;
recycleVelocityTracker();
break;
}
}
return wasScrolling || mIsScrolling;
}
private void requestParentDisallowInterceptTouchEvent() {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
private void catchView() {
ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent ev) {
boolean handled = false;
if (mZoomEnabled && hasDrawable((ImageView) v)) {
ViewParent parent = v.getParent();
switch (ev.getAction()) {
case ACTION_DOWN:
// First, disable the Parent from intercepting the touch
// event
if (null != parent) {
parent.requestDisallowInterceptTouchEvent(true);
} else {
LogManager.getLogger().i(LOG_TAG, "onTouch getParent() returned null");
}
// If we're flinging, and the user presses down, cancel
// fling
cancelFling();
break;
case ACTION_CANCEL:
case ACTION_UP:
// If the user has zoomed less than min scale, zoom back
// to min scale
if (getScale() < mMinScale) {
RectF rect = getDisplayRect();
if (null != rect) {
v.post(new AnimatedZoomRunnable(getScale(), mMinScale,
rect.centerX(), rect.centerY()));
handled = true;
}
}
break;
}
// Try the Scale/Drag detector
if (null != mScaleDragDetector) {
boolean wasScaling = mScaleDragDetector.isScaling();
boolean wasDragging = mScaleDragDetector.isDragging();
handled = mScaleDragDetector.onTouchEvent(ev);
boolean didntScale = !wasScaling && !mScaleDragDetector.isScaling();
boolean didntDrag = !wasDragging && !mScaleDragDetector.isDragging();
mBlockParentIntercept = didntScale && didntDrag;
}
// Check to see if the user double tapped
if (null != mGestureDetector && mGestureDetector.onTouchEvent(ev)) {
handled = true;
}
}
return handled;
}
private void requestParentDisallowInterceptTouchEvent(boolean disallowIntercept) {
final ViewParent parent = getParent();
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}