Search code examples
androidandroid-viewpagerandroid-scrollview

ScrollView inside ViewPager: swipe not working


I have ViewPager with three fragments and one of them is FrameLayout with ScrollView inside:

<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>

and if I swipe over button, it works. But if I swipe over the ScrollView, it doesn't work, only scroll up/down works

EDIT: I tried to override OnTouchEvent of Scrollview:

@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;
}

Now I can disable scroll, but swipe still not working, if the difference between X points more than 40, I pass the event to the viewpager, but the viewpager's onTouchListener doesn't get this event;


Solution

  • Ok, I found the solution with help of @yedidyak. I wrote my custom 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);
    }
    }
    

    then in the fragment I put the viewpager to this view and it works perfectly