【问题标题】:ScrollView inside ViewPager: swipe not workingViewPager 中的 ScrollView:滑动不起作用
【发布时间】:2016-03-19 00:18:36
【问题描述】:

我有三个片段的 ViewPager,其中之一是 FrameLayout,里面有 ScrollView:

<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没有收到这个事件;

【问题讨论】:

标签: android android-viewpager android-scrollview


【解决方案1】:

对于生活在 +2019 年的未来读者

使用ViewPager2 来避免这个问题。 你可以在 topic 找到 ViewPager2 实现的好例子。

【讨论】:

    【解决方案2】:

    好的,我在@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 会如何影响滚动?更大 = 更多区域?还是对面?
    • 我会这么说:这个数字 (40) 越小,垂直滚动视图所需的垂直移动就越精确。例如。如果设置为 400,则永远无法左右滑动,只能上下滚动。如果设置为 4 - 否则,您将永远不会滚动,只能滑动。
    • 非常感谢,帮了大忙。
    • 能看到完整的项目吗?我看不到您如何在 Fragment 类的 CustomScrollView 中设置 parentPager。谢谢
    • 在你的 Fragment 的onCreateView() 中你可以像ViewPager parentPager = (ViewPager) rootView.findViewById(&lt;id&gt;); 然后CustomScrollView scrollView= (CustomScrollView ) rootView.findViewById(&lt;id&gt;); 然后scrollView.setParentPager()parentPager 那样做
    【解决方案3】:

    问题是不清楚你想要发生什么滚动,是 ViewPager 还是滚动视图。如果你真的需要一个scroll-inside-a-scroll,那么你需要重写内部scrollview的OnTouchListener并添加代码来决定何时捕捉和使用触摸,以及何时将其传递回父视图。

    在这种情况下,您可以执行一些操作来测试滑动是否向上/向下,然后保持触摸,否则如果滑动是侧向的,则将其传回。

    【讨论】:

    • 谢谢,你的想法很清楚。但是如何拆分这两个事件,上/下和左/右?
    • 如果操作失败,则存储 X 和 Y 值。然后在下一个动作中检查发生了更多变化。如果 X 的变化大于 Y 的变化,那么它是横向的。有很多代码教程用于使用触摸事件来识别手势。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 2012-09-22
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    相关资源
    最近更新 更多