SlidingUpPanelLayout and ScrollView
Asked Answered
F

7

5

I have a SlidingUpPanelLayout that holds a image as a top view, and a view pager that needs to slide. The viewpager has 3 fragments and two of them are list views. So I want to be able to expand the view pager on pulling up, and once the view pager is up I want to be able to scroll the scrollviews inside the fragments. But when pulling down on the scrollview in case there is no more to scroll, I want to start collapsing the viewpager. So please suggest how to make the SlidingUpPanelLayout collapse on pulling the scrollview in case there is no more contents to scroll?

Here I post some of my code: I have tried capture the touch events and overwrite the SlidingUpPanel onInterceptTouchEvent function in the following way:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (isHandled) {
        Log.i("interceptToch", "HEREEE");
        return onTouchEvent(ev);
    }
    return false;
}

So when the SlidingUpPanelLayout is expanded I set isHandled = false. So when the slidingUpPanelLayout expands, all touch events are passed to its child views.

And I also put onTouchEvent in the scrollView, in-order to unblock the SlidingUpPanelLayout.onInterceptTouchEvent:

public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
        scroll = 0;
        y = event.getY();
    } else if (action == MotionEvent.ACTION_MOVE) {
        if (scroll_view_summary.getScrollY() == 0 && event.getY() > y) {
            scroll = scroll + 1;
            if (scroll > 2) {
                // the user has pulled the list and the slidingUpPanelLauout 
                // should be able to handle the toch events again
                SlidingUpPanelLayoutCustom las = 
                    ((SaleDetailsActivity) getActivity()).getLayout();
                las.setHandle(true);
                scroll = 0;
                return false;
            }
        }
    }
    return false;
}

But this is not working. The problem is that once the scrollview.onTouch event is in MotionEvent.ACTION_MOVE SlidingUpPanelLayout.onInterceptTouchEvent is not called. SlidingUpPanelLayout.onInterceptTouchEvent is called after MotionEvent.ACTION_CANCEL. This means that the event can't be passed to the SlidingUpPanelLayout and the panel can't collapse.

Factorize answered 18/3, 2014 at 11:43 Comment(0)
L
15

Unfortunately you can't rely on SlidingUpPanelLayout's onInterceptTouchEvent method for the aforementioned reasons. Once a child view's onTouchEvent method returns true, onInterceptTouchEvent is no longer called.

My solution is a bit convoluted, but it allows you to achieve exactly what (I think) you're looking for. A single touch/drag event will drag the panel into place and, once in place, continue scrolling the child view. Likewise when dragging down, a single touch/drag event can scroll the child view and, once completely scrolled, will begin dragging the panel down.

Updated 2015-04-12 Updated to version 3.0.0 of the SlidingUpPanelLayout code. Also accounting for ListViews instead of just ScrollViews.

1) In the res/ folder of SlidingUpPanel's library project, open the attrs.xml and add

<attr name="scrollView" format="reference" />

You'll use this to identify a single child view that will usurp the touch event once the panel has been dragged into position. In your layout xml file, you can then add

sothree:scrollView="@+id/myScrollView"

Or whatever the ID of your scrollView is. Also make sure that you do not declare a sothree:dragView ID, so the entire view is draggable.

The rest of the steps are all done within SlidingUpPanelLayout.java...

2) Declare the following variables:

View mScrollView;
int mScrollViewResId = -1;
boolean isChildHandlingTouch = false;
float mPrevMotionX;
float mPrevMotionY;

3) In the constructor, just after mDragViewResId is set, add the following line:

mScrollViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_scrollView, -1);

4) In onFinishInflate, add the following code:

if (mScrollViewResId != -1) {
    mScrollView = findViewById(mScrollViewResId);
}

5) Add the following method:

private boolean isScrollViewUnder(int x, int y) {
    if (mScrollView == null)
        return false;

    int[] viewLocation = new int[2];
    mScrollView.getLocationOnScreen(viewLocation);
    int[] parentLocation = new int[2];
    this.getLocationOnScreen(parentLocation);
    int screenX = parentLocation[0] + x;
    int screenY = parentLocation[1] + y;
    return screenX >= viewLocation[0] && 
           screenX < viewLocation[0] + mScrollView.getWidth() && 
           screenY >= viewLocation[1] && 
           screenY < viewLocation[1] + mScrollView.getHeight();
}

6) Remove onInterceptTouchEvent.

7) Modify onTouchEvent to the following:

public boolean onTouchEvent(MotionEvent ev) {
    if (!isEnabled() || !isTouchEnabled()) {
        return super.onTouchEvent(ev);
    }
    try {
        mDragHelper.processTouchEvent(ev);

        final int action = ev.getAction();
        boolean wantTouchEvents = false;

        switch (action & MotionEventCompat.ACTION_MASK) {
            case MotionEvent.ACTION_UP: {
                final float x = ev.getX();
                final float y = ev.getY();
                final float dx = x - mInitialMotionX;
                final float dy = y - mInitialMotionY;
                final int slop = mDragHelper.getTouchSlop();
                View dragView = mDragView != null ? mDragView : mSlideableView;

                if (dx * dx + dy * dy < slop * slop &&
                        isDragViewUnder((int) x, (int) y) &&
                        !isScrollViewUnder((int) x, (int) y)) {
                    dragView.playSoundEffect(SoundEffectConstants.CLICK);

                    if ((PanelState.EXPANDED != mSlideState) && (PanelState.ANCHORED != mSlideState)) {
                        setPanelState(PanelState.ANCHORED);
                    } else {
                        setPanelState(PanelState.COLLAPSED);
                    }
                    break;
                }
                break;
            }
        }

        return wantTouchEvents;
    } catch (Exception ex) {
        ex.printStackTrace();
        return false;
    }
}

8) Add the following method:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    // Identify if we want to handle the touch event in this class.
    // We do this here because we want to be able to handle the case
    // where a child begins handling a touch event, but then the
    // parent takes over. If we rely on onInterceptTouchEvent, we
    // lose control of the touch as soon as the child handles the event.
    if (mScrollView == null)
        return super.dispatchTouchEvent(ev);

    final int action = MotionEventCompat.getActionMasked(ev);

    final float x = ev.getX();
    final float y = ev.getY();

    if (action == MotionEvent.ACTION_DOWN) {
        // Go ahead and have the drag helper attempt to intercept
        // the touch event. If it won't be dragging, we'll cancel it later.
        mDragHelper.shouldInterceptTouchEvent(ev);

        mInitialMotionX = mPrevMotionX = x;
        mInitialMotionY = mPrevMotionY = y;

        isChildHandlingTouch = false;
    } else if (action == MotionEvent.ACTION_MOVE) {
        float dx = x - mPrevMotionX;
        float dy = y - mPrevMotionY;
        mPrevMotionX = x;
        mPrevMotionY = y;

        // If the scroll view isn't under the touch, pass the
        // event along to the dragView.
        if (!isScrollViewUnder((int) x, (int) y))
            return this.onTouchEvent(ev);

        // Which direction (up or down) is the drag moving?
        if (dy > 0) { // DOWN
            // Is the child less than fully scrolled?
            // Then let the child handle it.
            if (isScrollViewScrolling()) {
                isChildHandlingTouch = true;
                return super.dispatchTouchEvent(ev);
            }

            // Was the child handling the touch previously?
            // Then we need to rejigger things so that the
            // drag panel gets a proper down event.
            if (isChildHandlingTouch) {
                // Send an 'UP' event to the child.
                MotionEvent up = MotionEvent.obtain(ev);
                up.setAction(MotionEvent.ACTION_UP);
                super.dispatchTouchEvent(up);
                up.recycle();

                // Send a 'DOWN' event to the panel. (We'll cheat
                // and hijack this one)
                ev.setAction(MotionEvent.ACTION_DOWN);
            }

            isChildHandlingTouch = false;
            return this.onTouchEvent(ev);
        } else if (dy < 0) { // UP
            // Is the panel less than fully expanded?
            // Then we'll handle the drag here.
            if (mSlideOffset < 1.0f) {
                isChildHandlingTouch = false;
                return this.onTouchEvent(ev);
            }

            // Was the panel handling the touch previously?
            // Then we need to rejigger things so that the
            // child gets a proper down event.
            if (!isChildHandlingTouch) {
                mDragHelper.cancel();
                ev.setAction(MotionEvent.ACTION_DOWN);
            }

            isChildHandlingTouch = true;
            return super.dispatchTouchEvent(ev);
        }
    } else if ((action == MotionEvent.ACTION_CANCEL) ||
            (action == MotionEvent.ACTION_UP)) {
        if (!isChildHandlingTouch) {
            final float dx = x - mInitialMotionX;
            final float dy = y - mInitialMotionY;
            final int slop = mDragHelper.getTouchSlop();

            if ((mIsUsingDragViewTouchEvents) && (dx * dx + dy * dy < slop * slop))
                return super.dispatchTouchEvent(ev);

            return this.onTouchEvent(ev);
        }
    }

    // In all other cases, just let the default behavior take over.
    return super.dispatchTouchEvent(ev);
}

9) Add the following method to determine whether the scrollView is still scrolling. Handles cases for both ScrollView and ListView:

/**
 * Computes the scroll position of the the scrollView, if set.
 * @return
 */
private boolean isScrollViewScrolling() {
    if (mScrollView == null)
        return false;

    // ScrollViews are scrolling when getScrollY() is a value greater than 0.
    if (mScrollView instanceof ScrollView) {
        return (mScrollView.getScrollY() > 0);
    }
    // ListViews are scrolling if the first child is not displayed, or if the first child has an offset > 0
    else if (mScrollView instanceof ListView) {
        ListView lv = (ListView) mScrollView;

        if (lv.getFirstVisiblePosition() > 0)
            return true;

        View v = lv.getChildAt(0);
        int top = (v == null) ? (0) : (-v.getTop() + lv.getFirstVisiblePosition() * lv.getHeight());
        return top > 0;
    }

    return false;
}

10) (Optional) Add the following method to allow you to set the scrollView at runtime (i.e. You want to put a fragment in the panel, and the fragment's child has a ScrollView/ListView you want to scroll):

public void setScrollView(View scrollView) {
    mScrollView = scrollView;
}

We're now completely managing the handling of the touch event from within this class. If we're dragging the panel up and it slides fully into place, we cancel the drag and then spoof a new touch in the mScrollView child. If we're scrolling the child and reach the top, we spoof an "up" event in the child and spoof a new touch for the drag. This also allows tap events on other child widgets.

Known Issues The "up"/"down" events that we're spoofing can unintentionally trigger a click event on a child element of the scrollView.

Langobardic answered 28/3, 2014 at 18:9 Comment(19)
I should note that this solution assumes that no explicit dragView is ever set, so the entire panel is draggable.Langobardic
so i have a view pager that needs to be scroll up and down, thing is if i put the viewpager in a scrollview, the sothree:scrollView="@+id/myScrollView" than the view pager is white for some reason, there are no fragments in the view pagerFactorize
<ScrollView android:id="@+id/myscrollview" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/sale_details_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </ScrollView>Factorize
this happens also even if i don't change the com.sothree.slidinguppanel.SlidingUpPanelLayout libraryFactorize
Do you have this example as a working sample? Looks really interesting but feel like some steps are missing. Can't see how the class would get a reference to scrollView set in the xml and also how mScrollViewResId points to correct view with calling with findViewBy Id?Dorris
Thank you for your amazing answer. It works brilliantly! The only thing to add is if (mSlideOffset > 0.0f) { needs to be changed to if (mSlideOffset < 1.0f) { because when the panel is fully expanded the slide offset is 1.Harslet
Also, to enable the touch events of views not on sliding panel I changed the dispatchTouchEvent a bit: instead of returning this.onTouchEvent() I returned this.onTouchEvent(ev) || super.dispatchTouchEvent(ev) for the cases when the panel is not in dragging mode (not fully expanded/collapsed, not dragging)Harslet
what is mCanSlide from onTouchEvent(MotionEvent ev)?Cervantez
mCanSlide is a boolean member variable that appears throughout the class file. It's a flag that's set only when the onMeasure method is able to find a child view that has a visibility other than GONE.Langobardic
I had implement it, i could slide the panel but scrollview doesnot recognize its touch events and is not scrolling. I have been trying to edit ondispatchtouchevent(), can you provide brief your logic you used there. I was planning to implement it by 1) dispatch touch event to scrollView only when panel is expanded and 2)Listen for scroll changes and when user has action-down-movement and when scroll reaches top child dispatch touch event for panel drag. But I got a blank in how touch event works for slidingpanelLayout. Currently I am using a workAround, it works but I am not satisfied with itCervantez
Currenlty my workAround is initially i disable scrollview by returning true for scrooview touch listener and when in expanded state enable scrollview by passing null to touch listener and use a listener to know when scroll reaches top. when scroll reaches top smooth slide the panel programmatically and bring it to collapsed state and when anchored again disable scrollView. If I could detect scroll changes from slidingUpPanlelayout I could do it more neatlyCervantez
Can you please post the full class code? The scroll view works normally for me and thats it. The SlidingPanel no longer slidesUsed
@Langobardic Hi.. Actually my main content view is a map which should be always touchable and panable. I have to show this scrollview in slideuppanel only on marker click. As I see, this code doesn't allow me to touch the main content view. How can I achieve this behavior?Jessiejessika
This solution uses member variables and methods that don't exist (anymore?). So it's unusable for the current version (3.0.0).Boult
It looks as though the version I built this solution around is 2.2, and I see that there have been updates to 3.0.0 recently.Langobardic
@Langobardic So if the version is 2.2, and this solution is used, it works if the main content is a map?Jessiejessika
@DeepakSenapati, I assume you mean you want the map that the scrollView is covering up to continue to accept touch input? Or is the map contained within the scrollView?Langobardic
@Langobardic Yes the first one. I want the map that the scrollView is covering up to continue to accept touch input.Jessiejessika
The field wantTouchEvents is declared inside the onTouchEvent method but it always return false, so why it's here?Kaifeng
M
6

I had the same issue but at my app there is ListView instead of ScrollView. I couldn't apply themarshal's answer to work for my problem. But I have found solution on the basis of themarshal's, Chris's answers and Maria Sakharova's comments

First I couldn't find variables mCanSlide and mIsSlidingEnabled and methods expandPane(mAnchorPoint) and collapsePane() so I use next code:

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (!isEnabled() || !isTouchEnabled()) {
        return super.onTouchEvent(ev);
    }
    try {
        mDragHelper.processTouchEvent(ev);

        final int action = ev.getAction();
        boolean wantTouchEvents = false;

        switch (action & MotionEventCompat.ACTION_MASK) {
            case MotionEvent.ACTION_UP: {
                final float x = ev.getX();
                final float y = ev.getY();
                final float dx = x - mInitialMotionX;
                final float dy = y - mInitialMotionY;
                final int slop = mDragHelper.getTouchSlop();
                View dragView = mDragView != null ? mDragView : mSlideableView;

                if (dx * dx + dy * dy < slop * slop &&
                        isDragViewUnder((int) x, (int) y) &&
                        !isScrollViewUnder((int) x, (int) y)) {
                    dragView.playSoundEffect(SoundEffectConstants.CLICK);
                    if (!isExpanded() && !isAnchored()) {
                        //expandPane(mAnchorPoint);
                        setPanelState(PanelState.ANCHORED);
                    } else {
                        //collapsePane();
                        setPanelState(PanelState.COLLAPSED);
                    }
                    break;
                }
                break;
            }
        }

        return wantTouchEvents;
    } catch (Exception ex){
        ex.printStackTrace();
        return false;
    }
}

try/catch is needed because of exception raises when apply two fingers.

Second Chris's answers is obligatory to fulfill.

And then because of ListView's method getScrollY() always returns zero I change slightly code at method dispatchTouchEvent(MotionEvent ev):

this:

if (mScrollView.getScrollY() > 0) {
   isChildHandlingTouch = true;
   return super.dispatchTouchEvent(ev);
}

to:

if (((ListView)mScrollView).getFirstVisiblePosition() > 0 ||             getFirstChildTopOffset((ListView) mScrollView) > 0){
   isChildHandlingTouch = true;
   return super.dispatchTouchEvent(ev);
} 

//at some other place in class SlidingUpPanelLayout 
public int getFirstChildTopOffset(ListView list){
    View v = list.getChildAt(0);
    int top = (v == null) ? 0 : (list.getPaddingTop() - v.getTop());
    return top;
}

Also my app has Google Map as main content and it also must get MotionEvent so as Maria Sakharova said we must return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev) instead of this.onTouchEvent(ev) at two places. We must change this code:

if (!isScrollViewUnder((int) x, (int) y))
   return this.onTouchEvent(ev);

to:

if (!isScrollViewUnder((int) x, (int) y))
   return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev);

in this case super.dispatchTouchEvent(ev) is needed if main content must get MotionEvent.

And second code:

} else if ((action == MotionEvent.ACTION_CANCEL) ||
            (action == MotionEvent.ACTION_UP)) {
    if (!isChildHandlingTouch) {
        final float dx = x - mInitialMotionX;
        final float dy = y - mInitialMotionY;
        final int slop = mDragHelper.getTouchSlop();

        if ((mIsUsingDragViewTouchEvents) &&
                    (dx * dx + dy * dy < slop * slop))
            return super.dispatchTouchEvent(ev);

        return this.onTouchEvent(ev);
    }
}

to:

} else if ((action == MotionEvent.ACTION_CANCEL) ||
            (action == MotionEvent.ACTION_UP)) {
   if (!isChildHandlingTouch) {
        final float dx = x - mInitialMotionX;
        final float dy = y - mInitialMotionY;
        final int slop = mDragHelper.getTouchSlop();

        if ((mIsUsingDragViewTouchEvents) &&
                    (dx * dx + dy * dy < slop * slop))
            return super.dispatchTouchEvent(ev);

        return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev);
    }
}

in this case super.dispatchTouchEvent(ev) is needed to able to expand panel.

In summary method dispatchTouchEvent(MotionEvent ev) will be the next:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    // Identify if we want to handle the touch event in this class.
    // We do this here because we want to be able to handle the case
    // where a child begins handling a touch event, but then the
    // parent takes over. If we rely on onInterceptTouchEvent, we
    // lose control of the touch as soon as the child handles the event.
    if (mScrollView == null)
        return super.dispatchTouchEvent(ev);

    final int action = MotionEventCompat.getActionMasked(ev);

    final float x = ev.getX();
    final float y = ev.getY();

    if (action == MotionEvent.ACTION_DOWN) {
        // Go ahead and have the drag helper attempt to intercept
        // the touch event. If it won't be dragging, we'll cancel it later.
        mDragHelper.shouldInterceptTouchEvent(ev);

        mInitialMotionX = mPrevMotionX = x;
        mInitialMotionY = mPrevMotionY = y;

        isChildHandlingTouch = false;
    } else if (action == MotionEvent.ACTION_MOVE) {
        float dx = x - mPrevMotionX;
        float dy = y - mPrevMotionY;
        mPrevMotionX = x;
        mPrevMotionY = y;

        // If the scroll view isn't under the touch, pass the
        // event along to the dragView.
        if (!isScrollViewUnder((int) x, (int) y))
            //return this.onTouchEvent(ev);
            return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev);

        // Which direction (up or down) is the drag moving?
        if (dy > 0) { // DOWN
            // Is the child less than fully scrolled?
            // Then let the child handle it.
            //if (mScrollView.getScrollY() > 0) {
            if (((ListView)mScrollView).getFirstVisiblePosition() > 0 || getFirstChildTopOffset((ListView) mScrollView) > 0){
                isChildHandlingTouch = true;
                return super.dispatchTouchEvent(ev);
            }

            // Was the child handling the touch previously?
            // Then we need to rejigger things so that the
            // drag panel gets a proper down event.
            if (isChildHandlingTouch) {
                // Send an 'UP' event to the child.
                MotionEvent up = MotionEvent.obtain(ev);
                up.setAction(MotionEvent.ACTION_UP);
                super.dispatchTouchEvent(up);
                up.recycle();

                // Send a 'DOWN' event to the panel. (We'll cheat
                // and hijack this one)
                ev.setAction(MotionEvent.ACTION_DOWN);
            }

            isChildHandlingTouch = false;
            return this.onTouchEvent(ev);
        } else if (dy < 0) { // UP
            // Is the panel less than fully expanded?
            // Then we'll handle the drag here.
            //if (mSlideOffset > 0.0f) {
            if (mSlideOffset < 1.0f) {
                isChildHandlingTouch = false;
                return this.onTouchEvent(ev);
                //return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev);
            }

            // Was the panel handling the touch previously?
            // Then we need to rejigger things so that the
            // child gets a proper down event.
            if (!isChildHandlingTouch) {
                mDragHelper.cancel();
                ev.setAction(MotionEvent.ACTION_DOWN);
            }

            isChildHandlingTouch = true;
            return super.dispatchTouchEvent(ev);
        }
    } else if ((action == MotionEvent.ACTION_CANCEL) ||
            (action == MotionEvent.ACTION_UP)) {
        if (!isChildHandlingTouch) {
            final float dx = x - mInitialMotionX;
            final float dy = y - mInitialMotionY;
            final int slop = mDragHelper.getTouchSlop();

            if ((mIsUsingDragViewTouchEvents) &&
                    (dx * dx + dy * dy < slop * slop))
                return super.dispatchTouchEvent(ev);

            //return this.onTouchEvent(ev);
            return this.onTouchEvent(ev) || super.dispatchTouchEvent(ev);
        }
    }

    // In all other cases, just let the default behavior take over.
    return super.dispatchTouchEvent(ev);
}
Methodism answered 24/1, 2015 at 10:26 Comment(0)
O
4

Since 3.1.0, Umano SlidingUpPanelLayout support nested scrolling with ScrollView, ListView and RecyclerView out of the box.

In most of the cases, simply add the sothree:umanoScrollableView attribute in your XML layout file, as following :

<com.sothree.slidinguppanel.SlidingUpPanelLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sothree="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sliding_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    sothree:umanoScrollableView="@+id/my_scrollable_view"
    android:gravity="bottom"
    sothree:umanoAnchorPoint="0.3"
    sothree:umanoPanelHeight="@dimen/bottom_playlist_height"
    sothree:umanoShadowHeight="4dp"
    android:paddingTop="?attr/actionBarSize">

For further information, look at this link : https://github.com/umano/AndroidSlidingUpPanel#scrollable-sliding-views

Orthodox answered 12/7, 2016 at 9:44 Comment(0)
P
2

Wow! 4 years have passed! But the question is still relevant. At least for me. I found a solution in a small section of the code and without modifying the library. It works fine with ScrollView.

public class MySlidingUpPanelLayout extends SlidingUpPanelLayout {
    public void setScrollViewInside(final ScrollViewInsideSlidingUpPanelLayout scroll){
        this.addPanelSlideListener(new PanelSlideListener() {
            @Override public void onPanelSlide(View panel, float slideOffset) {}

            @Override
            public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) {
                if(scroll!=null) {
                    scroll.setScrollable(getPanelState() == PanelState.EXPANDED);
                }
            }
        });
    }
}

public class ScrollViewInsideSlidingUpPanelLayout extends ScrollView {
    private boolean scrollable = false;
    public void setScrollable(boolean scrollable){
        this.scrollable = scrollable;
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);

        if (getScrollY() == 0) {
            scrollable = false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(scrollable)
            return super.onTouchEvent(event);
        else
            return false;
    }
}

usage:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    sliding_layout.setScrollViewInside(scroll);
}
Pose answered 2/3, 2018 at 21:36 Comment(0)
L
0

In order for JJD's answer to work you need to add another step

8) add this method mScrollViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_scrollView, -1); in the constructor of the SlidingPanelLayout

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

      ...

    if (attrs != null) {
            ...

        if (ta != null) {

                   ...

            mScrollViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_scrollView, -1);

                   ...
        }

        ta.recycle();
    }

}
Lenni answered 8/1, 2015 at 16:59 Comment(0)
W
0

Just use setScrollableView!

Example:

public View onCreateView(
    @NonNull LayoutInflater inflater, 
    ViewGroup container,
    Bundle savedInstanceState) {
    ((SlidingUpPanelLayout)findViewById(R.id.view))
        .setScrollableView(findViewById(R.id.scrollable));
}

Scrollable view can be is RecyclerView, ListView, ScrollView etc.

Weightless answered 23/11, 2017 at 16:48 Comment(0)
L
0

Would like to add to PAD's answer.

create a new NestedScrollableViewHelper class which will extends ScrollableViewHelper as directed in https://github.com/umano/AndroidSlidingUpPanel#scrollable-sliding-views

and then set it in your mainActivity:

slidingUpPanelLayout = findViewById(R.id.slidingpanel); slidingUpPanelLayout.setScrollableViewHelper(new NestedScrollableViewHelper());

without this, SlidingUpPanel is not intercepting the touch while scrolling down in inner nestedscrollview or scrollview and is scrolling the SlidingUpPanel itself down.

scrolling up is working fine.

Loudspeaker answered 1/6, 2019 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.