Skip to content

Commit

Permalink
[BottomSheet] Handle half-expanded state when drag handle clicked
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 461674745
(cherry picked from commit ef8e9aa)
  • Loading branch information
drchen committed Aug 4, 2022
1 parent 92caa19 commit f0e6625
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 11 deletions.
Expand Up @@ -57,6 +57,7 @@ public class BottomSheetDragHandleView extends AppCompatImageView

private boolean accessibilityServiceEnabled;
private boolean interactable;
private boolean clickToExpand;

private final String clickToExpandActionLabel =
getResources().getString(R.string.bottomsheet_action_expand);
Expand Down Expand Up @@ -104,7 +105,7 @@ public BottomSheetDragHandleView(
public void onPopulateAccessibilityEvent(View host, @NonNull AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(host, event);
if (event.getEventType() == TYPE_VIEW_CLICKED) {
toggleBottomSheetIfPossible();
expandOrCollapseBottomSheetIfPossible();
}
}
});
Expand Down Expand Up @@ -148,15 +149,16 @@ private void setBottomSheetBehavior(@Nullable BottomSheetBehavior<?> behavior) {
}

private void onBottomSheetStateChanged(@BottomSheetBehavior.State int state) {
String label =
state == BottomSheetBehavior.STATE_COLLAPSED
? clickToExpandActionLabel
: clickToCollapseActionLabel;
if (state == BottomSheetBehavior.STATE_COLLAPSED) {
clickToExpand = true;
} else if (state == BottomSheetBehavior.STATE_EXPANDED) {
clickToExpand = false;
} // Else keep the original settings
ViewCompat.replaceAccessibilityAction(
this,
AccessibilityActionCompat.ACTION_CLICK,
label,
(v, args) -> toggleBottomSheetIfPossible());
clickToExpand ? clickToExpandActionLabel : clickToCollapseActionLabel,
(v, args) -> expandOrCollapseBottomSheetIfPossible());
}

private void updateInteractableState() {
Expand All @@ -169,14 +171,41 @@ private void updateInteractableState() {
setClickable(interactable);
}

private boolean toggleBottomSheetIfPossible() {
/**
* Expands or collapses the associated bottom sheet according to the current state and the
* previous state when the drag handle is interactable, .
*
* <p>If the current state is COLLAPSED or EXPANDED and the bottom sheet can be half-expanded, it
* will make the bottom sheet HALF_EXPANDED; if the bottom sheet cannot be half-expanded, it will
* be EXPANDED (when it's COLLAPSED) or COLLAPSED (when it's EXPANDED) instead. On the other hand
* when the bottom sheet is HALF_EXPANDED, it will make the bottom sheet either COLLAPSED (when
* the previous state was EXPANDED) or EXPANDED (when the previous state was COLLAPSED.)
*/
private boolean expandOrCollapseBottomSheetIfPossible() {
if (!interactable) {
return false;
}
announceAccessibilityEvent(clickFeedback);
boolean collapsed = bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED;
bottomSheetBehavior.setState(
collapsed ? BottomSheetBehavior.STATE_EXPANDED : BottomSheetBehavior.STATE_COLLAPSED);
boolean canHalfExpand =
!bottomSheetBehavior.isFitToContents()
&& !bottomSheetBehavior.shouldSkipHalfExpandedStateWhenDragging();
int currentState = bottomSheetBehavior.getState();
int nextState;
if (currentState == BottomSheetBehavior.STATE_COLLAPSED) {
nextState =
canHalfExpand
? BottomSheetBehavior.STATE_HALF_EXPANDED
: BottomSheetBehavior.STATE_EXPANDED;
} else if (currentState == BottomSheetBehavior.STATE_EXPANDED) {
nextState =
canHalfExpand
? BottomSheetBehavior.STATE_HALF_EXPANDED
: BottomSheetBehavior.STATE_COLLAPSED;
} else {
nextState =
clickToExpand ? BottomSheetBehavior.STATE_EXPANDED : BottomSheetBehavior.STATE_COLLAPSED;
}
bottomSheetBehavior.setState(nextState);
return true;
}

Expand Down
Expand Up @@ -122,6 +122,79 @@ public void test_collapseExpandedBottomSheetWhenClicked() {
.isEqualTo(BottomSheetBehavior.STATE_COLLAPSED);
}

@Test
public void test_collapsedBottomSheetMoveToHalfExpanded_whenClickedAndFitToContentsFalse() {
activity.bottomSheetBehavior.setFitToContents(false);
activity.bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
activity.addViewToBottomSheet(dragHandleView);
shadowOf(accessibilityManager).setEnabled(true);
dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

assertThat(activity.bottomSheetBehavior.getState())
.isEqualTo(BottomSheetBehavior.STATE_HALF_EXPANDED);
}

@Test
public void test_expandedBottomSheetMoveToHalfExpanded_whenClickedAndFitToContentsFalse() {
activity.bottomSheetBehavior.setFitToContents(false);
activity.bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
activity.addViewToBottomSheet(dragHandleView);
shadowOf(accessibilityManager).setEnabled(true);

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

assertThat(activity.bottomSheetBehavior.getState())
.isEqualTo(BottomSheetBehavior.STATE_HALF_EXPANDED);
}

@Test
public void test_halfExpandedBottomSheetMoveToExpanded_whenPreviouslyCollapsed() {
activity.bottomSheetBehavior.setFitToContents(false);
activity.bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
activity.addViewToBottomSheet(dragHandleView);
shadowOf(accessibilityManager).setEnabled(true);

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

assertThat(activity.bottomSheetBehavior.getState())
.isEqualTo(BottomSheetBehavior.STATE_EXPANDED);
}

@Test
public void test_halfExpandedBottomSheetMoveToCollapsed_whenPreviouslyExpanded() {
activity.bottomSheetBehavior.setFitToContents(false);
activity.bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
activity.addViewToBottomSheet(dragHandleView);
shadowOf(accessibilityManager).setEnabled(true);

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

dragHandleView.performClick();

InstrumentationRegistry.getInstrumentation().waitForIdleSync();

assertThat(activity.bottomSheetBehavior.getState())
.isEqualTo(BottomSheetBehavior.STATE_COLLAPSED);
}

private void assertImportantForAccessibility(boolean important) {
if (important) {
assertThat(ViewCompat.getImportantForAccessibility(dragHandleView))
Expand Down

0 comments on commit f0e6625

Please sign in to comment.