ScrollView的child在触摸child并垂直滚动时无法获取ACTION_MOVE和ACTION_UP事件

ScrollView's child cannot get ACTION_MOVE and ACTION_UP event when touch child and scroll vertically

我在 ScrollView 中有一些视图。问题是当我触摸 child 视图并垂直滚动它时,child 视图只能获得 ACTION_DOWNACTION_CANCEL 事件。错过了 ACTION_MOVEACTION_UP 事件。
如果我触摸 child 视图并水平滚动它,child 视图可以按预期获得所有触摸事件。
这是我的代码:
xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/sv_test_tv"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:gravity="center"
            android:text="This is some text."
            android:textSize="30sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#faa" />

        <View
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#faf" />

    </LinearLayout>

</ScrollView>

java代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sv_test);

        TextView tv = (TextView) findViewById(R.id.sv_test_tv);
        tv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                LogUtils.v("ScrollViewTest", "onTouch:" + getType(event.getAction()));

                return true;
            }
        });

    }

    private String getType(int type) {
        switch (type) {
            case MotionEvent.ACTION_DOWN: {
                return "ACTION_DOWN";
            }

            case MotionEvent.ACTION_MOVE: {
                return "ACTION_MOVE";
            }

            case MotionEvent.ACTION_UP: {
                return "ACTION_UP";
            }
        }

        return "other:" + type;
    }

谁能帮帮我?非常感谢

发生这种情况是因为 ScrollView 拦截了 移动事件, 查看 ScrollView 源代码 onInterceptTouchEvent(MotionEvent ev) 这样会更清楚。 如果您想在 ScrollView 中使用 ScrollView,那么我建议您查看 this answer

您可以将自定义滚动视图添加到布局中。 创建您的自定义 scrollView 并在您的布局中使用它。

public class VerticalScrollview extends ScrollView{

    public VerticalScrollview(Context context) {
        super(context);
    }

    public VerticalScrollview(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
                super.onTouchEvent(ev);
                break;

            case MotionEvent.ACTION_MOVE:
                return false; // redirect MotionEvents to ourself

            case MotionEvent.ACTION_CANCEL:
                super.onTouchEvent(ev);
                break;

            case MotionEvent.ACTION_UP:
                return false;

            default:  break;
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        //Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
        return true;
    }
}

添加 <packagename..VerticalScrollview /> 代替 ScrollView。

试试这个

onInterceptTouchEvent only gets ACTION_DOWN

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
MyLog.d(MyLog.DEBUG, "dispatchTouchEvent(): "+event.getAction());
if (isEnabled()) {
    MyLog.d(MyLog.DEBUG, "dispatchTouchEvent()2: "+event.getAction());

    processEvent(event);//here you get all events include move & up

    super.dispatchTouchEvent(event);

    return true; //to keep receive event that follow down event
}
return super.dispatchTouchEvent(event);
}

尝试使用这条线

sv_test_tv.setMovementMethod(new ScrollingMovementMethod());

在 Activity 文件中