ListView in BottomSheet
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.
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;
}
});
Starting from version 22.1.0, you might want to try setNestedScrollingEnabled=true
If this property is set to true the view will be permitted to initiate nested scrolling operations with a compatible parent view in the current hierarchy. If this view does not implement nested scrolling this will have no effect. Disabling nested scrolling while a nested scroll is in progress has the effect of stopping the nested scroll.
Reference to Google API
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;
}
}