ListView in BottomSheet

前端 未结 8 2296
梦毁少年i
梦毁少年i 2020-12-13 07:39

I ran into a problem where I had a simple ListView in a BottomSheet and ListView had enough items to fill the screen and scroll even m

相关标签:
8条回答
  • 2020-12-13 07:44

    The solution is to extend the ListView like this:

    public class BottomSheetListView extends ListView {
        public BottomSheetListView (Context context, AttributeSet p_attrs) {
            super (context, p_attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return true;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (canScrollVertically(this)) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            return super.onTouchEvent(ev);
        }
    
        public boolean canScrollVertically (AbsListView view) {
            boolean canScroll = false;
    
            if (view !=null && view.getChildCount ()> 0) {
                boolean isOnTop = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0;
                boolean isAllItemsVisible = isOnTop && view.getLastVisiblePosition() == view.getChildCount();
    
                if (isOnTop || isAllItemsVisible) {
                    canScroll = true;
                }
            }
    
            return  canScroll;
        }
    }
    

    Then in your layout file bottom_sheet_view.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.mypackage.name.BottomSheetListView
            android:id="@+id/listViewBtmSheet"
            android:divider="@color/colorPrimary"
            android:dividerHeight="1dp"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="0dp" />
    
    </LinearLayout>
    

    Then finally, in your Activity/Fragment:

    BottomSheetDialog dialog = new BottomSheetDialog(context);
    dialog.setContentView(R.layout.bottom_sheet_view);
    
    BottomSheetListView listView = (BottomSheetListView) dialog.findViewById(R.id.listViewBtmSheet);
    // apply some adapter - add some data to listview
    
    dialog.show();
    

    This will provide a BottomSheet that is fully working with ListView scroll.

    0 讨论(0)
  • 2020-12-13 07:47

    This is the correct list view custom class with touch event hadnling

    public class BottomSheetListView extends ListView
    {
        public BottomSheetListView(Context context, AttributeSet p_attrs)
        {
            super(context, p_attrs);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev)
        {
            if (canScrollVertically(this))
            {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            return super.onInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev)
        {
            if (canScrollVertically(this))
            {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            return super.onTouchEvent(ev);
        }
    
        public boolean canScrollVertically(AbsListView view)
        {
            boolean canScroll = false;
    
            if (view != null && view.getChildCount() > 0)
            {
                boolean isOnTop = view.getFirstVisiblePosition() != 0 || view.getChildAt(0).getTop() != 0;
                boolean isAllItemsVisible = isOnTop && view.getLastVisiblePosition() == view.getChildCount();
    
                if (isOnTop || isAllItemsVisible)
                {
                    canScroll = true;
                }
            }
    
            return canScroll;
        }
    }
    
    0 讨论(0)
  • 2020-12-13 07:49

    There is a better approach if you don't want to extend the ListView:

    //in onCreate
    
    _listView.setOnTouchListener(new ListView.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    int action = event.getAction();
                    switch (action) {
                        case MotionEvent.ACTION_DOWN:
                            // Disallow NestedScrollView to intercept touch events.
                            v.getParent().requestDisallowInterceptTouchEvent(true);
                            break;
    
                        case MotionEvent.ACTION_UP:
                            // Allow NestedScrollView to intercept touch events.
                            v.getParent().requestDisallowInterceptTouchEvent(false);
                            break;
                    }
    
                    // Handle ListView touch events.
                    v.onTouchEvent(event);
                    return true;
                }
            });
    
    0 讨论(0)
  • 2020-12-13 07:51

    Just set android:nestedScrollingEnabled to true inside your layout as ListView attribute or listView.setNestedScrollingEnabled(true) in java.

    0 讨论(0)
  • 2020-12-13 07:54

    I know it's a bit hack but it worked for me, and even listview is selectable. As we know that when ever bottom sheet change its state it can be caught in it's listener so don't let it change the state if listview is not touching top, henceforth touch event will be passed to listview and will work as it does.

        mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback(){
    @Override
    public void onStateChanged(View bottomSheet, int newState) {
            if (newState == BottomSheetBehavior.STATE_DRAGGING && !listIsAtTop()){
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
    }
    @Override
    public void onSlide(View bottomSheet, float slideOffset) {}});
    
    public boolean listIsAtTop()   {
        if(tripListView.getChildCount() == 0) return true;
        return (tripListView.getChildAt(0).getTop() == 0 && tripListView.getFirstVisiblePosition() ==0);
    }
    
    0 讨论(0)
  • 2020-12-13 07:56
    public class BottomSheetListView extends ListView {
    
        public BottomSheetListView(Context context, AttributeSet attributeSet) {
            super(context, attributeSet);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
            View view = (View) getChildAt(getChildCount() - 1);
    
            int diffBottom = (view.getBottom() - (getHeight() + getScrollY()));
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                if (diffBottom == 0) {
                    return false;
                }
            }
    
             /*//Need more improvement on this logic. Do not uncomment
            int diffTop = (view.getTop() - (getHeight() + getScrollY()));
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                if (diffTop < 0) {
                    return true;
                }
            }*/
    
            return super.onInterceptTouchEvent(motionEvent);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent motionEvent) {
            if (canScrollVertically(this)) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            return super.onTouchEvent(motionEvent);
        }
    
        public boolean canScrollVertically(AbsListView absListView) {
    
            boolean canScroll = false;
    
            if (absListView != null && absListView.getChildCount() > 0) {
    
                boolean isOnTop = absListView.getFirstVisiblePosition() != 0 || absListView.getChildAt(0).getTop() != 0;
                boolean isAllItemsVisible = isOnTop && getLastVisiblePosition() == absListView.getChildCount();
    
                if (isOnTop || isAllItemsVisible)
                    canScroll = true;
            }
    
            return canScroll;
        }
    }
    
    0 讨论(0)
提交回复
热议问题