ViewPager 内的 ScrollView:滑动不工作

ScrollView inside ViewPager: swipe not working

我有包含三个片段的 ViewPager,其中之一是带有 ScrollView 的 FrameLayout:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/table"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"/>
    </ScrollView>

    <Button
        android:id="@+id/buttonRemove"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_button_red"
        android:layout_gravity="bottom"
        android:layout_margin="4dp"
        android:text="@string/button_remove_last_round"
        android:textColor="#ffffff"
        android:textSize="24sp"/>


</FrameLayout>

如果我在按钮上滑动,它就会起作用。但是如果我在 ScrollView 上滑动,它不起作用,只有滚动 up/down 有效

编辑:我试图覆盖 Scrollview 的 OnTouchEvent:

@Override
public boolean onTouchEvent(MotionEvent ev) {

    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            touchX = ev.getX();
            touchY = ev.getY();
            return super.onTouchEvent(ev);//if I change it to 'break', then only swipe works, but no scroll
        case MotionEvent.ACTION_MOVE:
            if(Math.abs(touchX-ev.getX())<40){
                return super.onTouchEvent(ev);//Scroll works perfectly
            }else{
                return false;//Scroll disabled, but swipe still not working
            }
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            touchX=0;
            touchY=0;
            break;
    }
    return false;
}

现在我可以关闭scroll了,但是swipe还是不行,如果X点之间的差超过40,我把事件传给viewpager,但是viewpager的onTouchListener没有得到这个事件;

问题是不清楚你想要发生什么滚动,是 ViewPager 的滚动还是滚动视图的滚动。如果你真的需要滚动内部滚动,那么你需要覆盖内部滚动视图的 OnTouchListener 并添加决定何时捕获和使用触摸以及何时将其传递回父视图的代码。

在这种情况下,您可以做一些事情来测试滑动是否 up/down,然后保持触摸,否则如果滑动是横向的,则将其传回。

好的,我在@yedidyak 的帮助下找到了解决方案。我写了我的自定义 ScrollView:

public class CustomScrollView extends ScrollView {

float touchX = 0;
float touchY = 0;

ViewPager parentPager;

public void setParentPager(ViewPager parentPager) {
    this.parentPager = parentPager;
}

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

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

@Override
public boolean onTouchEvent(MotionEvent ev) {

    switch (ev.getActionMasked()){
        case MotionEvent.ACTION_DOWN:
            touchX = ev.getX();
            touchY = ev.getY();
            return super.onTouchEvent(ev);
        case MotionEvent.ACTION_MOVE:
            if(Math.abs(touchX-ev.getX())<40){
                return super.onTouchEvent(ev);
            }else{
                if (parentPager==null) {
                    return false;
                } else {
                    return parentPager.onTouchEvent(ev);
                }
            }
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            touchX=0;
            touchY=0;
            break;
    }
    return super.onTouchEvent(ev);
}
}

然后在片段中,我将 viewpager 放到这个视图中,它工作得很好

For Future Readers living in +2019

使用ViewPager2 来避免这个问题。 您可以在此 .

找到 ViewPager2 实现的良好示例