umano / AndroidSlidingUpPanel

This library provides a simple way to add a draggable sliding up panel (popularized by Google Music and Google Maps) to your Android application. Brought to you by Umano.
http://umano.me
Apache License 2.0
9.5k stars 2.26k forks source link

Panel not expanding while user is touching the screen. #749

Open mtyy opened 8 years ago

mtyy commented 8 years ago

I want to be 100% sure that panel slides to EXPANDED state no matter what. However when user is in middle of a listview/viewpager scroll and possibly other touch interactions, the panel does not appear.

this is basically what happens:

onPanelStateChanged() called with: previousState = [COLLAPSED], newState = [DRAGGING]
onPanelSlide() called with: slideOffset = [1.0]
onPanelStateChanged() called with: previousState = [DRAGGING], newState = [COLLAPSED]

starts dragging and collapses instantly.

I can work around this with disabling touch events. By overriding dispatchTouchEvent(MotionEvent ev)to return true (without calling super) before setting setPanelState(Panelstate.EXPANDED) and until onPanelStateChanged()newState is EXPANDED.

however this seems super hacky and unreliable. Maybe you guys have more ideas how to tackle it?

trieulh-ict commented 8 years ago

I also got this error while scrolling a listview. I set a timer to auto-expand the panel after a fixed time. But when the timer end while I'm scrolling the listview, the Panel is not expanded and gets the same state as you showed. @mtyy can you show me your temporality solution?

Thank in advance.

lawsonk1215 commented 8 years ago

I had the same issue because I was disabling the user from interacting with the panel and setting the state programmatically. If the user clicked anywhere on the root layout while the panel was moving, the panel would get stuck and stop expanding or collapsing.

I was able to use @mtyy's suggestion and override the dispatchTouchEvent(MotionEvent ev) and only returning the super if the panel state was dragging.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
   return this.getPanelState() == PanelState.DRAGGING || super.dispatchTouchEvent(ev);
}
tentypwtk commented 8 years ago

In my case, when drawer is collapsing or expanding, a tap on the screen will stop the animation. My workaround, put a view (visibility:gone) above the sliding layout and apply the following actions:

`slidingLayout.addPanelSlideListener(new SlidingUpPanelLayout.PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) {

        }

        @Override
        public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState prevState, SlidingUpPanelLayout.PanelState newState) {
            if( ( prevState == SlidingUpPanelLayout.PanelState.COLLAPSED || prevState == SlidingUpPanelLayout.PanelState.EXPANDED ) && newState == SlidingUpPanelLayout.PanelState.DRAGGING ) {
                clickInterceptor.setVisibility(View.VISIBLE);
            }
            else if( prevState == SlidingUpPanelLayout.PanelState.DRAGGING && ( newState == SlidingUpPanelLayout.PanelState.COLLAPSED || newState == SlidingUpPanelLayout.PanelState.EXPANDED ) ) {
                clickInterceptor.setVisibility(View.GONE);
            }

        }
    });`

Anyone with a knowledge of a nicer solution - let me know.

keiferstone commented 6 years ago

We encountered this issue today. I was able to fix it by modifying SlidingUpPanelLayout#dispatchTouchEvent() to only call ViewDragHelper#abort() if ViewDragHelper is in STATE_IDLE.

I've created PR #917 to fix this issue.

appsbyusman commented 4 years ago

I also ran into this issue. This happens when we tap outside the panel (non-panel area) when the panel is sliding. Here, the newState is set to ANCHORED. So we can force it to slide down to COLLAPSED.

This would be natural for the user as he had already tapped outside the panel which means that he wanted to touch the area behind it.

@Override public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState previousState, SlidingUpPanelLayout.PanelState newState) {

            switch (newState) {
                case EXPANDED:
                    // your logic
                    break;
                case COLLAPSED:
                    // your logic
                    break;
                case ANCHORED:
                    // this is when we tap outside the panel when it is sliding. Here, we will force it to slide down to COLLAPSED.
                    slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
                    break;
            }
        }

To escape the aftermath of these unintended touches on objects (buttons, etc) while you are not ready to act on those touches, use setFadeOnClickListener so all the touches are forwarded to our SlidingUpPanelLayout where we will not do anything about these touches.