material-components / material-components/material-components-android

[BottomSheetBehavior] Bottom Sheet State always set to `STATE_EXPANDED` when swiping up

Open
#2,335 6 comments 1 reaction 1 assignee View on GitHub

Nobody has claimed this yet.

bug Widget: BottomSheet
Dominant language
Java
Stars
17.4k
Forks
3.2k
PR merge metrics
No merged PRs in 30d

Description

Description:
When Bottom Sheet's flag fitToContents is set to default value true, the bottom sheet will always set its state to STATE_EXPANDED whenever a swipe up gesture is performed on the bottom sheet, even tho the content is not long enough to be expanded to full screen, i.e. swiping up result in NO VISUAL CHANGES to the UI.

A side effect of the above is that, in a "non-expandable" bottom sheet, when we do swipe up gesture, it will think itself been set to STATE_EXPANDED and then invalidate the bottom sheet drawable, which will make the top corners of the bottom sheet flat (from rounded top corners)

Take the blow recording as a example:

STATE_COLLAPSED -> STATE_EXPANDED by swiping up

https://user-images.githubusercontent.com/5491995/132157081-d8cb280d-9c87-4f3c-85de-bcdd6c5c9b4e.mp4

STATE_EXPANDED -> STATE_COLLAPSED by swiping down

https://user-images.githubusercontent.com/5491995/132157228-fd3bed03-eabf-4015-b851-704024990131.mp4

STATE_EXPANDED -> STATE_COLLAPSED by swiping down on BottomSheetDialog, release it and let itself auto settle

https://user-images.githubusercontent.com/5491995/132157269-dfcb7fc3-7b1d-43be-b4a5-bc019ce3a35e.mp4

Expected behavior:
This might be controversial but there are two directions we would expect:

  • NEVER have STATE_COLLAPSED for a short bottom sheet that fitToContent == true, (this will involve fix for other use cases to prevent the state becomes STATE_COLLAPSED) OR
  • Prevent the bottom sheet's state to become STATE_EXPANDED when we tries to swipe up

Source code:

@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
  int top;
  @State int targetState;
  if (yvel < 0) { // Moving up
    if (fitToContents) {
      top = fitToContentsOffset;
      targetState = STATE_EXPANDED;    <<<-------- This is where we need to ad extra logic
    } else {
      int currentTop = releasedChild.getTop();
      if (currentTop > halfExpandedOffset) {
        top = halfExpandedOffset;
        targetState = STATE_HALF_EXPANDED;
      } else {
        top = getExpandedOffset();
        targetState = STATE_EXPANDED;
      }
    }
  } else if (hideable && shouldHide(releasedChild, yvel)) {
    ...
  } else if (yvel == 0.f || Math.abs(xvel) > Math.abs(yvel)) {
    // If the Y velocity is 0 or the swipe was mostly horizontal indicated by the X velocity
    // being greater than the Y velocity, settle to the nearest correct height.
    ...
  } else { // Moving Down
   ...
  }
  startSettlingAnimation(releasedChild, targetState, top, true);
}

Proposed Solution for the 2nd approach above (as it will not impact other uses cases)

if (yvel < 0) { // Moving up
  if (fitToContents) {
    // Keep it at collapsed state when the collapsed height and expanded height are the same,
    // i.e. content is not long enough to visually expand the bottom sheet
    if (fitToContentsOffset == collapsedOffset) {
      top = collapsedOffset;
      targetState = STATE_COLLAPSED;
    } else {
      top = fitToContentsOffset;
      targetState = STATE_EXPANDED;
    }
  }
} else if (...) { ... } 

Android API version: API 29

Material Library version: 1.5.0-alpha02

Device: ONE PLUS 8 PRO

To help us triage faster, please check to make sure you are using the latest version of the library.

We also happily accept pull requests.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.