24

I'm trying to put a ScrollView inside another ScrollView and I tried the answers found on this site but it still doesn't seems to work completely. Here is the XML:

 <ScrollView
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusableInTouchMode="false" >

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

        <TextView
            android:id="@+id/textViewDirectoryDetailName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Name"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textColor="@color/red" />

        <LinearLayout
            android:id="@+id/linearLayoutDirectoryDetailContainImage"
            android:layout_width="300dp"
            android:layout_height="200dp"
            android:layout_gravity="center_vertical|center_horizontal"
            android:background="@drawable/general_image"
            android:gravity="center"
            android:orientation="vertical" >
        </LinearLayout>

        <ScrollView
            android:id="@+id/scrollView2"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:focusableInTouchMode="false" >

            <TextView
                android:id="@+id/textViewDirectoryDescription"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:autoLink="phone"
                android:text="098 123 45 678"
                android:textAppearance="?android:attr/textAppearanceLarge" />
        </ScrollView>

And here is the Java code:

parentScrollView = (ScrollView) findViewById(R.id.scrollView1);
    childScrollView = (ScrollView) findViewById(R.id.scrollView2);

    parentScrollView.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View p_v, MotionEvent p_event) {
            childScrollView.getParent().requestDisallowInterceptTouchEvent(
                    false);
            // We will have to follow above for all scrollable contents
            return false;
        }
    });
    childScrollView.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View p_v, MotionEvent p_event) {
            // this will disallow the touch request for parent scroll on
            // touch of child view
            p_v.getParent().requestDisallowInterceptTouchEvent(true);
            return false;
        }
    });
    // We will have to follow above for all child scrollable contents

What seems to happen is this: when I have text in the TextView it doesn't seem to let me scroll it at all. It just scrolls the parent. But when I have no text and I touch the child ScrollView it doesn't scroll the parent so I guess it's working then. But do you have any ideas why it doesn't work when I have text?

Mihai Boisteanu
  • 563
  • 1
  • 4
  • 15
  • 2
    *I'm trying to put a ScrollView inside another ScrollView* - don't do this, how do expect the scroll to work when you have two different scroll areas? – user Feb 17 '14 at 08:56
  • this is a bad idea actually. – i.n.e.f Feb 17 '14 at 08:58
  • Remove scrollView2. Why did you put it there in the first place, what are you trying to achieve ? – 2Dee Feb 17 '14 at 08:59
  • 1
    I'm working on this app for a client and he already has this implemented in IOS. The thing is that the description for some items might be too long, in which case I use the child scroll view to scroll down. I have seen people do it so I want to do it as well. – Mihai Boisteanu Feb 17 '14 at 09:03
  • This may be helpful for you http://grishma102.blogspot.in/2014/01/handle-scrolling-of-scrollable-controls.html – Gopal Gopi Feb 17 '14 at 09:09

9 Answers9

52

You should use NestedScrollView.

<android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
            <!-- -->
</android.support.v4.widget.NestedScrollView>
Volodymyr Kulyk
  • 6,455
  • 3
  • 36
  • 63
  • 1
    I had another project with the same issue and this worked. Thanks you! – Mihai Boisteanu May 24 '17 at 07:24
  • 2
    This was an easy solution. I used it for the inner scroll view only; it wasn't necessary to change the outer scroll view. – arlomedia Oct 05 '21 at 22:55
  • BTW, iOS and Android handle nested scrolling a bit differently. On iOS, touching inside the inner scroll view will only scroll the inner view, while touching outside the inner scroll view but inside the outer scroll view will scroll the outer view. On Android with NestedScrollView, touching inside the inner scroll view will scroll the inner view until it reaches its scroll limit in either direction, and will then start scrolling the outer view. – arlomedia Oct 05 '21 at 22:59
5

Old Question though, I am posting what worked for me,I understand the issue Coz i have gone through it too, I just removed the ScrollView for TextView in XML, rather implemented scrolling feature for TextView in java code. Thus, XML would be:

    <TextView
        android:id="@+id/textViewDirectoryDetailName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Name"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/red" />

    <LinearLayout
        android:id="@+id/linearLayoutDirectoryDetailContainImage"
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:layout_gravity="center_vertical|center_horizontal"
        android:background="@drawable/general_image"
        android:gravity="center"
        android:orientation="vertical" >
    </LinearLayout>   
            <TextView
            android:id="@+id/textViewDirectoryDescription"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:autoLink="phone"
            android:text="098 123 45 678"
            android:textAppearance="?android:attr/textAppearanceLarge" />

and the Java Code would be

 TextView extViewDD =  
    (TextView)findViewById(R.id.textViewDirectoryDescription);    
    //for Scrolling of textView       
    textViewDD.setMovementMethod(new ScrollingMovementMethod());
//to stop parent linearlayout scrollview when touched on textview
    textViewDD.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.getParent().requestDisallowInterceptTouchEvent(true);
            return false;
        }
    });
Dev Gurung
  • 1,290
  • 14
  • 16
2

Having a Scroll View inside another another Scroll View is not a good practice. However the code you have used could work in some cases. But it might fail when you are having multiple elements. In that case, it might not be able to identify the gesture.

However, you can try this answer, if it helps ScrollView Inside ScrollView. It disables the parent ScrollView's touch, when a touch for the child is identified. Also have a look at this post if it helps.

Community
  • 1
  • 1
Sahil Mahajan Mj
  • 11,033
  • 8
  • 53
  • 100
  • I have tried those methods but I'm always getting PARENT TOUCH in the logs and never CHILD TOUCH. – Mihai Boisteanu Feb 17 '14 at 09:48
  • Sorry, I cant understand what you are saying. Can you show what you have tried and where you are facing the problem. – Sahil Mahajan Mj Feb 17 '14 at 09:57
  • I mean most methods are the same. I have used for example this one: [link](http://grishma102.blogspot.in/2014/01/handle-scrolling-of-scrollable-controls.html) and when I touch the child scrollview it still says that I have touched the parent, and it doesn't work at all. – Mihai Boisteanu Feb 18 '14 at 07:42
2

I use RectF to test whether you finger locates in the range of your child_view.

I've used it for a case that a mix between scrollview and viewpager(that contains two pages with recycleviews).

Try these codes and you will get what you wanna.

findViewById(R.id.parent_view).setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            View childV = findViewById(R.id.child_view);
            if (childV != null) {
                int[] l = new int[2];
                childV.getLocationOnScreen(l);
                RectF rect = new RectF(l[0], l[1], l[0] + childV.getWidth(), l[1] + childV.getHeight());
                if(rect.contains(  event.getX(), event.getY())) {
                    childV.getParent()
                            .requestDisallowInterceptTouchEvent(false);
                    childV.onTouchEvent(event);
                    return true;
                }
            }
            childV.getParent()
                    .requestDisallowInterceptTouchEvent(true);
            return false;
        }
    });
TeeTracker
  • 7,064
  • 8
  • 40
  • 46
0

check this link which shows that how to use two widget with scroll functionality in same activity. check this below code in that.

parentScroll.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                Log.v("PARENT", "PARENT TOUCH");
                findViewById(R.id.child_scroll).getParent()
                        .requestDisallowInterceptTouchEvent(false);
                return false;
            }
        });
        childScroll.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                Log.v("CHILD", "CHILD TOUCH");
                // Disallow the touch request for parent scroll on touch of
                // child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });
Community
  • 1
  • 1
i.n.e.f
  • 1,773
  • 13
  • 22
  • This is literary the same code I have above, except for the logs, but I'll give this a try as well, just to be 100% sure. – Mihai Boisteanu Feb 17 '14 at 09:05
  • It's not working at all. And the logs always say "PARENT TOUCH" and never "CHILD TOUCH" so I guess I can't touch the child scrollview. – Mihai Boisteanu Feb 18 '14 at 07:44
0

you can not use two Scrollview inside Scrollview OS get confuse which one have to scroll so your activity hang so do not use like this

venky
  • 64
  • 5
0

I'm almost sure it is impossible:

How android handles touch events:

Parent gets event and decides if it has to handle it or if it should let handle it to the child;

so,if a scrollview handles the touch, the one which handles it, is always the parent one

http://developer.android.com/training/gestures/viewgroup.html

personally i don't know if is there a way to understand what is touched behind the parent scrollview to see if it is another scrollview and let it handle the movement

cescom
  • 116
  • 6
0

Here is a possible solution which works fine with ScrollView and ListView inside a ScrollView. ScrollView Inside ScrollView

Community
  • 1
  • 1
Nicolai Nita
  • 173
  • 9
0

use this custom scrollview as inner scrollview:

public class TouchMeScrollView extends ScrollView {
public TouchMeScrollView(Context context) {
    super(context);
}

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

public TouchMeScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TouchMeScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(ev);
}
}
Hanaa Mohamed
  • 107
  • 2
  • 11