1

I have some views in ScrollView. The problem is when I touch the child view and scroll it vertically, the child view can only get ACTION_DOWN and ACTION_CANCEL event. The ACTION_MOVE and ACTION_UP event is missed.
If I touch the child view and scroll it horizontally, the child view can get all the touch event just as expected.
Here is my code:
xml file:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/sv_test_tv"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:gravity="center"
            android:text="This is some text."
            android:textSize="30sp" />

        <View
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#faa" />

        <View
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#faf" />

    </LinearLayout>

</ScrollView>

java code:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sv_test);

        TextView tv = (TextView) findViewById(R.id.sv_test_tv);
        tv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                LogUtils.v("ScrollViewTest", "onTouch:" + getType(event.getAction()));

                return true;
            }
        });

    }

    private String getType(int type) {
        switch (type) {
            case MotionEvent.ACTION_DOWN: {
                return "ACTION_DOWN";
            }

            case MotionEvent.ACTION_MOVE: {
                return "ACTION_MOVE";
            }

            case MotionEvent.ACTION_UP: {
                return "ACTION_UP";
            }
        }

        return "other:" + type;
    }

Anyone can help me? Thanks a lot.

hanswim
  • 1,182
  • 8
  • 20

4 Answers4

3

You can add custom scrollview to your layout. Create your custom scrollView and use it in your layout.

public class VerticalScrollview extends ScrollView{

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

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

    public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        switch (action)
        {
            case MotionEvent.ACTION_DOWN:
                super.onTouchEvent(ev);
                break;

            case MotionEvent.ACTION_MOVE:
                return false; // redirect MotionEvents to ourself

            case MotionEvent.ACTION_CANCEL:
                super.onTouchEvent(ev);
                break;

            case MotionEvent.ACTION_UP:
                return false;

            default:  break;
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        //Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
        return true;
    }
}

Add <packagename..VerticalScrollview /> in place of ScrollView.

dn_c
  • 614
  • 1
  • 9
  • 26
1

This happens because the ScrollView intercepts the move event, Take a look at the ScrollView source code at onInterceptTouchEvent(MotionEvent ev) and it will be clearer. If u want a ScrollView inside of a ScrollView then i would suggest to take a look at this answer

Community
  • 1
  • 1
EE66
  • 4,601
  • 1
  • 17
  • 20
  • 1
    Thank you very much. I know the reason now. I just have a TextView in ScrollView and I want the user can touch and move the position of the TextView. Thanks for @dn_c 's help I have solved my problem now. – hanswim Jul 15 '15 at 09:45
0

Try this one

onInterceptTouchEvent only gets ACTION_DOWN

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
MyLog.d(MyLog.DEBUG, "dispatchTouchEvent(): "+event.getAction());
if (isEnabled()) {
    MyLog.d(MyLog.DEBUG, "dispatchTouchEvent()2: "+event.getAction());

    processEvent(event);//here you get all events include move & up

    super.dispatchTouchEvent(event);

    return true; //to keep receive event that follow down event
}
return super.dispatchTouchEvent(event);
}
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121
-1

Try using this line

sv_test_tv.setMovementMethod(new ScrollingMovementMethod());

in the Activity File