ViewPager 中的 ScrollView:滑动无效

3

我有一个包含三个片段的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上滑动,它不起作用,只有上下滚动才有效。
编辑:我尝试重写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;
}

现在我可以禁用滚动,但是滑动仍然无法工作,如果X点之间的差异大于40,我将事件传递给viewpager,但是viewpager的onTouchListener没有收到此事件;


请参考以下链接:https://dev59.com/CGgv5IYBdhLWcg3wSe62 - denvercoder9
3个回答

5

好的,我在@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放到这个视图中,它可以完美地工作。

太好了!我只有一个小问题。将那个40改成什么会影响滚动呢?更大=更多区域吗?还是相反? - Ayman Salah
2
我认为是这样的:数字越小(40),您的垂直移动就必须更精确才能垂直滚动视图。例如,如果您设置为400,则永远无法左右滑动,只能上下滚动有效。如果您设置为4,则反之亦然,您将永远无法滚动,只能左右滑动。 - Alexander Tumanin
非常感谢,那帮了大忙。 - Ayman Salah
能否看到完整的项目?我不知道你是如何从Fragment类中设置CustomScrollView的parentPager的。谢谢。 - Loebre
1
在你的Fragment的onCreateView()方法中,你可以这样做:ViewPager parentPager = (ViewPager) rootView.findViewById(<id>); 然后 CustomScrollView scrollView= (CustomScrollView ) rootView.findViewById(<id>); 接着 scrollView.setParentPager(parentPager) - Alexander Tumanin

1
问题在于不清楚您想要滚动的是ViewPager还是ScrollView。如果您真的需要在一个滚动视图内嵌套另一个滚动视图,那么您需要重写内部ScrollView的OnTouchListener并添加代码来决定何时捕获和使用触摸事件,何时将其传递回父视图。
在这种情况下,您可以编写一些测试代码以检测滑动方向,然后保留触摸事件,否则将其传递回去。

谢谢,你的想法很清晰。但是我如何分开这两个事件,上/下和左/右? - Alexander Tumanin
如果动作是向下的话,就存储X和Y的值。然后在下一个动作中检查哪个变化更大。如果X的变化大于Y的变化,那么就是横向移动。有很多关于使用触摸事件识别手势的代码教程可供参考。 - yedidyak

0
对于生活在+2019年的未来读者,请使用ViewPager2来避免这个问题。你可以在这个topic中找到ViewPager2实现的好例子。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接