拦截触摸事件嵌套滚动视图EditTexts和Spinners

时间:2015-08-03 23:42:21

标签: android android-edittext android-spinner android-scrollview motionevent

我有一个带有几个EditTexts,Spinners和SeekBars的片段,在你知道它之前,很难找到一块空格来在NestedScrollView里面滚动。它让UI感觉非常破碎。

我不确定它是否是一个错误,或者因为支持库尚未完成,但我想找到一种方法来强制EditTexts和Spinners仅拦截Clicks和LongClicks。似乎Scroll事件被忽略了。

编辑:这里感觉有点傻,但我确定了原因。我的布局中有一个元素设置为Visibility.Gone。当它是GONE时,滚动无法正常工作。现在我已经让它变得可见了,我没有任何滚动问题。

也许是错误的?

这是NestedScrollView的onInterceptTouchEvent(支持库的一部分)

@Override
public boolean onInterceptTouchEvent(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;
    }

    /*
     * Don't try to intercept touch if we can't scroll anyway.
     */
    if (getScrollY() == 0 && !ViewCompat.canScrollVertically(this, 1)) {
        return false;
    }

    switch (action & MotionEventCompat.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. mLastMotionY is set to the y 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 = MotionEventCompat.findPointerIndex(ev, activePointerId);
            if (pointerIndex == -1) {
                Log.e(TAG, "Invalid pointerId=" + activePointerId
                        + " in onInterceptTouchEvent");
                break;
            }

            final int y = (int) MotionEventCompat.getY(ev, pointerIndex);
            final int yDiff = Math.abs(y - mLastMotionY);
            if (yDiff > mTouchSlop
                    && (getNestedScrollAxes() & ViewCompat.SCROLL_AXIS_VERTICAL) == 0) {
                mIsBeingDragged = true;
                mLastMotionY = y;
                initVelocityTrackerIfNotExists();
                mVelocityTracker.addMovement(ev);
                mNestedYOffset = 0;
                final ViewParent parent = getParent();
                if (parent != null) {
                    parent.requestDisallowInterceptTouchEvent(true);
                }
            }
            break;
        }

        case MotionEvent.ACTION_DOWN: {
            final int y = (int) ev.getY();
            if (!inChild((int) ev.getX(), (int) y)) {
                mIsBeingDragged = false;
                recycleVelocityTracker();
                break;
            }

            /*
             * Remember location of down touch.
             * ACTION_DOWN always refers to pointer index 0.
             */
            mLastMotionY = y;
            mActivePointerId = MotionEventCompat.getPointerId(ev, 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 = !mScroller.isFinished();
            startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
            break;
        }

        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            /* Release the drag */
            mIsBeingDragged = false;
            mActivePointerId = INVALID_POINTER;
            recycleVelocityTracker();
            stopNestedScroll();
            break;
        case MotionEventCompat.ACTION_POINTER_UP:
            onSecondaryPointerUp(ev);
            break;
    }

    /*
    * The only time we want to intercept motion events is if we are in the
    * drag mode.
    */
    return mIsBeingDragged;
}

我认为应该强制拦截Scroll动作,但似乎不是。

这是我正在使用的MaterialEditText的onTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (singleLineEllipsis && getScrollX() > 0 && event.getAction() == MotionEvent.ACTION_DOWN && event.getX() < getPixel(4 * 5) && event.getY() > getHeight() - extraPaddingBottom - innerPaddingBottom && event.getY() < getHeight() - innerPaddingBottom) {
        setSelection(0);
        return false;
    }
    if (hasFocus() && showClearButton) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (insideClearButton(event)) {
                    clearButtonTouched = true;
                    clearButtonClicking = true;
                    return true;
                }
            case MotionEvent.ACTION_MOVE:
                if (clearButtonClicking && !insideClearButton(event)) {
                    clearButtonClicking = false;
                }
                if (clearButtonTouched) {
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (clearButtonClicking) {
                    if (!TextUtils.isEmpty(getText())) {
                        setText(null);
                    }
                    clearButtonClicking = false;
                }
                if (clearButtonTouched) {
                    clearButtonTouched = false;
                    return true;
                }
                clearButtonTouched = false;
                break;
            case MotionEvent.ACTION_CANCEL:
                clearButtonTouched = false;
                clearButtonClicking = false;
                break;
        }
    }
    return super.onTouchEvent(event);
}

和MaterialSpinner:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (isEnabled()) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isSelected = true;
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isSelected = false;
                break;
        }
        invalidate();
    }
    return super.onTouchEvent(event);
}

那里有什么明显的东西应该告诉我为什么Scroll Motion Events没有得到妥善处理?

编辑:我不确定我是否可以正确解释这一点,但似乎如果ErrorTexts显示每个水平布局中的至少一个项目,则滚动正常工作。将进一步调查......

0 个答案:

没有答案