Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent Android ScrollView from intercepting its parents click event

I know there are questions like this already with answers, but I'm not having any luck with anything, so this is a last resort.

I have a LinearLayout containing a ScrollView. I want the LinearLayout to respond to click, tap, touch whatever you want to call it, but the ScrollView is interfering, so the LinearLayout's click handler is never invoked. I don't mind sub-classing ScrollView and overriding onTouchEvent (but I don't understand what to put into it), but an alternative solution is fine too. I've tried using requestDisallowInterceptTouch(true) on the LinearLayout, the ScrollView and the first child of the ScrollView, but it's not working (TBH, the javadoc for that method confuses me).

If I use this override in my custom scrollview:

@Override
public boolean onTouchEvent(MotionEvent event) {
    return false;
}

...the LinearLayout does respond to taps, but scrolling is completely disabled, and every type of touch gesture results in the LinearLayout click handler being invoked. So, what do I need to do to let scrolling movements be handled as they normally would and also get the ScrollView to ignore clicks/taps?

For what it's worth, the XML looks something like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/my_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView 
        .../>

   <com.package.MyScrollView
        android:id="@+id/my_scroller"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fillViewport="true"
        android:scrollbars="vertical">
    ...  
    ...

Under normal circumstances, the TextView area will detect the click registered with the LinearLayout, but the ScrollView will not.

like image 647
RTF Avatar asked Nov 01 '22 07:11

RTF


1 Answers

First of all, requestDisallowInterceptTouch(true) unfortunately does completely the opposite of what you want to achieve. It forces all parent ViewGroups including the one on which you call the method to disregard events passed to them in onInterceptTouchEvent().

Normally, that is without setting setting this flag to true, new touch events are first passed from root to leaf all the way down the view tree which allows parents (i.e. ViewGroups) to intercept those events by returning true which redirects all following events of the same gesture to this ViewGroups onTouchEvent() method. After a view tree leaf is reached (assuming that no one has returned true in onInterceptTouchEvent()) the event bubbles back to the root via the onTouchEvent() method. Again returning true means that the event is consumed in the view doing so and all further events will be directly passed to your onTouchEvent() method rather than traversing through the whole view tree. So the difference between onInterceptTouch() and onTouch() is the direction of traversal through the view tree - reading all that I'm not really sure if it is more comprehensible than the javadoc.^^

Nevertheless, to put a long story short: requestDisallowInterceptTouchEvent(true) is no solution here.

That's for the prolog. Still here? Lucky you - because there is a (somewhat ugly) workaround for the situation you have observed: put a OnClickListener on the child of the ScrollView and let it performClick() on your LinearLayout that should do the trick. This will keep the ScrollView in a working state (unlike your attempt to override onTouch), but passes all click events (and only those) to the outer LinearLayout.

like image 118
ubuntudroid Avatar answered Nov 08 '22 05:11

ubuntudroid