ScrollView Inside ScrollView

后端 未结 13 712
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 15:40

I Know people from Google have asked us not to put Scrollable view inside another Scrollable view but is there any official statement from them directing us not to do so?

相关标签:
13条回答
  • 2020-11-22 15:46

    Android support v4 library has a class called NestedScrollView.

    Try Nested Scroll View: http://ivankocijan.xyz/android-nestedscrollview/

    0 讨论(0)
  • 2020-11-22 15:48

    Try this one

    Note: Here parentScrollView means Outer ScrollView And childScrollView means Innner ScrollView

    parentScrollView.setOnTouchListener(new View.OnTouchListener() {
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
            Log.v(TAG, "PARENT TOUCH");
    
            findViewById(R.id.child_scroll).getParent()
                    .requestDisallowInterceptTouchEvent(false);
            return false;
        }
    });
    
    childScrollView.setOnTouchListener(new View.OnTouchListener() {
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
            Log.v(TAG, "CHILD TOUCH");
    
            // Disallow the touch request for parent scroll on touch of  child view
            v.getParent().requestDisallowInterceptTouchEvent(true);
            return false;
        }
    });
    
    0 讨论(0)
  • 2020-11-22 15:56

    I found a very good solution. Please use this code.

        parentScrollView.setOnTouchListener(new View.OnTouchListener() {
    
            public boolean onTouch(View v, MotionEvent event) {
    
                Utils.showLog("PARENT TOUCH");
                findViewById(R.id.activity_mesh_child_scrollView).getParent().requestDisallowInterceptTouchEvent(false);
                return false;
            }
        });
    
        childScrollView.setOnTouchListener(new View.OnTouchListener() {
    
            public boolean onTouch(View v, MotionEvent event) {
    
                Utils.showLog("CHILD TOUCH");
                // Disallow the touch request for parent scroll on touch of child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });
    

    This will surely work. Please try and let me know if not working.

    0 讨论(0)
  • 2020-11-22 15:56

    If anyone is looking for an answer to this, I had a slightly different implementation. I extended the ScrollView class and implemented onTouchListener in the child, and set it to self in the constructor.

    In the onTouch callback, if the motion event object came with a value for pointer count as 2, I returned true, otherwise false. This way, if two fingers were moving on screen, it would consider it as a pinch to zoom, otherwise would consider it as normal scroll. I didn't request for parent touch disable etc.

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(motionEvent.getPointerCount() == 2){
            mCallbacks.onPinchZoomAction(motionEvent);
            return true;
        }
        return false;
    }
    
    0 讨论(0)
  • 2020-11-22 15:57

    Atul Bhardwaj's answer above is the correct way to do it. But in case someone needs to apply it to a ScrollView where you have less control of the parent, I think this is flexible enough and just the way it's supposed to work:

    private void makeMyScrollSmart() {
        myScroll.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View __v, MotionEvent __event) {
                if (__event.getAction() == MotionEvent.ACTION_DOWN) {
                    //  Disallow the touch request for parent scroll on touch of child view
                    requestDisallowParentInterceptTouchEvent(__v, true);
                } else if (__event.getAction() == MotionEvent.ACTION_UP || __event.getAction() == MotionEvent.ACTION_CANCEL) {
                    // Re-allows parent events
                    requestDisallowParentInterceptTouchEvent(__v, false);
                }
                return false;
            }
        });
    }
    
    private void requestDisallowParentInterceptTouchEvent(View __v, Boolean __disallowIntercept) {
        while (__v.getParent() != null && __v.getParent() instanceof View) {
            if (__v.getParent() instanceof ScrollView) {
                __v.getParent().requestDisallowInterceptTouchEvent(__disallowIntercept);
            }
            __v = (View) __v.getParent();
        }
    }
    

    What the function does is add a touch listener to myScroll that disables the parent's touch intercept when a touch starts in the child, and then enables it back when the touch actually ends. You don't need a reference to the parent ScrollView and it doesn't have to be the immediate parent... it'll travel the display list until it finds it.

    Best of both worlds, in my opinion.

    0 讨论(0)
  • 2020-11-22 16:05

    You can put a ScrollView inside another ScrollView. Just extend the child ScrollView to override the onTouchEvent method. Like so

    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    
    public class ChildScrollView extends android.widget.ScrollView {
        private int parent_id;
    
        public ChildScrollView(Context context) {
            super(context);
        }
    
        public ChildScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ChildScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event){
            requestDisallowInterceptTouchEvent(true);
            return super.onTouchEvent(event);
        }
    }
    
    0 讨论(0)
提交回复
热议问题