3
votes

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;

3

3 Answers

5
votes

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

1
votes

The problem is that it isn't clear what scroll you want to happen, that of the ViewPager or that of the scrollview. If you really need a scroll-inside-a-scroll, then you need to override the OnTouchListener of the inner scrollview and add code that decides when to catch and use the touch, and when to pass it back to the parent views.

In this case, you can do something that tests if the swipe is up/down, and then keep the touch, otherwise if the swipe is sideways then passes it back.

0
votes

For Future Readers living in +2019

use ViewPager2 to avoid this problem. you can find good example of ViewPager2 implementation at this topic.