android BottomSheet how to collapse when clicked outside?
Finally I was able to do this,
Used the following lines of code:
@Override public boolean dispatchTouchEvent(MotionEvent event){ if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mBottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED) { Rect outRect = new Rect(); bottomSheet.getGlobalVisibleRect(outRect); if(!outRect.contains((int)event.getRawX(), (int)event.getRawY())) mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } } return super.dispatchTouchEvent(event);}
Hope it save someone's whole day!
Thanks the OP for the question/answer. I've used his code but improved on its cleanliness and wanted to share. Instead of extending a View and adding the interface, you can code that directly in the BottomSheetBehavior. Like this:
AutoCloseBottomSheetBehavior.java
import android.content.Context;import android.graphics.Rect;import android.support.design.widget.BottomSheetBehavior;import android.support.design.widget.CoordinatorLayout;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;public class AutoCloseBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> { public AutoCloseBottomSheetBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && getState() == BottomSheetBehavior.STATE_EXPANDED) { Rect outRect = new Rect(); child.getGlobalVisibleRect(outRect); if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) { setState(BottomSheetBehavior.STATE_COLLAPSED); } } return super.onInterceptTouchEvent(parent, child, event); }}
and then you simply add it to your XML layout:
<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> ... your normal content here ... <SomeLayout... /> ... the bottom sheet with the behavior <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:layout_behavior="<com.package.name.of.the.class>.AutoCloseBottomSheetBehavior"> ... the bottom sheet views </LinearLayout></android.support.design.widget.CoordinatorLayout>
For Activity:
@Override public boolean dispatchTouchEvent(MotionEvent event){ if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mBottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED) { Rect outRect = new Rect(); bottomSheet.getGlobalVisibleRect(outRect); if(!outRect.contains((int)event.getRawX(), (int)event.getRawY())) mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } } return super.dispatchTouchEvent(event);}
For Fragment: Use same method in Activity like,
@Overridepublic boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (fragment != null && fragment instanceof HomeFragment) { ((HomeFragment) fragment).hideBottomSheetFromOutSide(event); } } return super.dispatchTouchEvent(event);}
and Create Method in Fragment like:
/** * Calling from Dashboard Activity * * @param event Motion Event */ public void hideBottomSheetFromOutSide(MotionEvent event) { if (isBottomSheetMenuExpanded()) { Rect outRect = new Rect(); mBinding.homeBottomSheetLayout.getGlobalVisibleRect(outRect); if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } }
Hope it will helps you.
Thank you.