I want to recreate Bottom Sheet Behavior provided in the Google Maps app:
Link to expected behavior.
I have tried using BottomSheetBehavior and couple of other 3rd party libs like umano AndroidSlidingUpPanel but the problem I was unable to avoid is they are all snapping the Bottom Sheet in between states (collapsed and expanded).
I would like to have a Bottom Sheet which can be smoothly expanded by sliding up, without it snapping to the closest state but instead to remain where the user stopped with the sliding.
You can achieve this by subclassing BottomSheetBehavior
, and overriding onTouchEvent
to return early on ACTION_UP
and ACTION_CANCEL
.
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
public CustomBottomSheetBehavior() {
super();
}
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return true;
}
return super.onTouchEvent(parent, child, event);
}
}
This prevents the BottomSheetBehavior
class from handling these events and triggering the 'expand' or 'collapse' call.
To apply your CustomBottomSheetBehavior
in xml:
app:layout_behavior="com.yourpackage.CustomBottomSheetBehavior"
To restore default functionality to the BottomSheetBehavior
when the sheet is fully expanded or collapsed, you can add a flag which is set when the slide offset reaches a certain value. In the following example, the bottom sheet ACTION_UP
and ACTION_CANCEL
events are only ignored when the slide offset is between 0.1 and 0.9.
public class CustomBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> {
private boolean isExpandedOrCollapsed;
public CustomBottomSheetBehavior() {
super();
listenForSlideEvents();
}
public CustomBottomSheetBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
listenForSlideEvents();
}
void listenForSlideEvents() {
setBottomSheetCallback(new BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
isExpandedOrCollapsed = slideOffset < 0.1f || slideOffset > 0.9f;
}
});
}
@Override
public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
if (!isExpandedOrCollapsed) {
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
return true;
}
}
return super.onTouchEvent(parent, child, event);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With