我有一个带有几个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显示每个水平布局中的至少一个项目,则滚动正常工作。将进一步调查......