Skip to content

Commit 9b44002

Browse files
hunterstichdsn5ft
authored andcommitted
Automated g4 rollback of changelist 694359774
PiperOrigin-RevId: 740806136
1 parent 5a44939 commit 9b44002

File tree

8 files changed

+183
-50
lines changed

8 files changed

+183
-50
lines changed

catalog/java/io/material/catalog/bottomsheet/BottomSheetUnscrollableContentDemoFragment.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
import android.view.LayoutInflater;
2424
import android.view.View;
2525
import android.view.ViewGroup;
26+
import android.widget.Button;
2627
import androidx.annotation.LayoutRes;
2728
import androidx.annotation.NonNull;
2829
import androidx.annotation.Nullable;
2930
import androidx.core.view.WindowInsetsCompat;
30-
import com.google.android.material.bottomsheet.BottomSheetBehavior;
3131
import com.google.android.material.bottomsheet.BottomSheetDialog;
3232
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
3333
import com.google.android.material.internal.ViewUtils;
@@ -67,7 +67,10 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
6767
new WindowPreferencesManager(requireContext()).applyEdgeToEdgePreference(bottomSheetDialog.getWindow());
6868
bottomSheetDialog.setContentView(R.layout.cat_bottomsheet_unscrollable_content);
6969
View bottomSheetInternal = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
70-
BottomSheetBehavior.from(bottomSheetInternal).setPeekHeight(400);
70+
// BottomSheetBehavior.from(bottomSheetInternal).setPeekHeight(400);
71+
72+
Button closeButton = bottomSheetDialog.findViewById(R.id.close_icon);
73+
closeButton.setOnClickListener(v -> bottomSheetDialog.dismiss());
7174

7275
View bottomSheetContent = bottomSheetInternal.findViewById(R.id.bottom_drawer_3);
7376
ViewUtils.doOnApplyWindowInsets(bottomSheetContent, (v, insets, initialPadding) -> {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!--
2+
Copyright 2024 The Android Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
<vector
18+
xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:height="24dp"
20+
android:width="24dp"
21+
android:viewportHeight="24"
22+
android:viewportWidth="24"
23+
android:tint="#000000">
24+
<path
25+
android:fillColor="@android:color/white"
26+
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
27+
</vector>

catalog/java/io/material/catalog/bottomsheet/res/layout/cat_bottomsheet_standard_content.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,14 @@
7474
android:text="@string/cat_bottomsheet_button_label_enabled"
7575
android:checked="true"/>
7676

77+
<com.google.android.material.materialswitch.MaterialSwitch
78+
android:id="@+id/cat_bottomsheet_hideable_switch"
79+
android:layout_width="wrap_content"
80+
android:layout_height="wrap_content"
81+
android:layout_below="@id/cat_bottomsheet_enabled_switch"
82+
android:layout_centerHorizontal="true"
83+
android:layout_marginTop="16dp"
84+
android:text="@string/cat_bottomsheet_hideable_switch_text"
85+
android:checked="false"/>
86+
7787
</merge>

catalog/java/io/material/catalog/bottomsheet/res/layout/cat_bottomsheet_unscrollable_content.xml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,27 @@
2020
android:layout_width="match_parent"
2121
android:layout_height="match_parent">
2222

23+
<!--
24+
Since we are providing a close affordance and this sheet does not have
25+
states to move between, disable a11y focus with
26+
importantForAccessibility=no and disable all announcements with
27+
contentDescription=null.
28+
-->
2329
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
2430
android:layout_width="match_parent"
25-
android:layout_height="wrap_content"/>
31+
android:layout_height="wrap_content"
32+
android:importantForAccessibility="no"
33+
android:contentDescription="@null"/>
34+
35+
<Button
36+
android:id="@+id/close_icon"
37+
style="?attr/materialIconButtonFilledTonalStyle"
38+
android:layout_width="wrap_content"
39+
android:layout_height="wrap_content"
40+
android:layout_gravity="end"
41+
android:layout_marginHorizontal="16dp"
42+
android:contentDescription="@string/cat_bottomsheet_close_content_description"
43+
app:icon="@drawable/ic_close_24dp"/>
2644

2745
<androidx.core.widget.NestedScrollView
2846
android:layout_width="match_parent"

catalog/java/io/material/catalog/bottomsheet/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
</string>
5252
<string name="cat_bottomsheet_button_label_enabled">Enabled</string>
5353
<string name="cat_bottomsheet_button_label_disabled">Disabled</string>
54+
<string name="cat_bottomsheet_hideable_switch_text" translatable="false">Hideable</string>
5455
<string name="cat_bottomsheet_button_clicked">Button clicked</string>
5556
<string name="cat_bottomsheet_scrollable_content_demo_title">
5657
Vertically scrollable content demo
@@ -66,4 +67,5 @@
6667
<string name="cat_bottomsheet_label_star">Star</string>
6768
<string name="cat_bottomsheet_label_remove">Remove</string>
6869
<string name="cat_bottomsheet_label_rename">Rename</string>
70+
<string name="cat_bottomsheet_close_content_description" translatable="false">Close modal sheet</string>
6971
</resources>

docs/components/BottomSheet.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,14 @@ The contents within a bottom sheet should follow their own accessibility
233233
guidelines, such as setting content descriptions for images.
234234

235235
To support dragging bottom sheets with accessibility services such as TalkBack,
236-
Voice Access, Switch Access, etc., we provide a convenient widget
237-
`BottomSheetDragHandleView` which will automatically receive and handle
236+
Voice Access, Switch Access, etc., we provide a convenient widget,
237+
`BottomSheetDragHandleView`, which will automatically receive and handle
238238
accessibility commands to expand and collapse the attached bottom sheet when
239-
the accessibility mode is enabled. To use `BottomSheetDragHandleView`, you can
240-
add it to the top of your bottom sheet content. It will show a customizable
241-
visual indicator for all users. See the example in the below section for how to
242-
add a drag handle to your bottom sheet.
239+
the accessibility mode is enabled. The handle also supports tapping to cycle
240+
through expanded and collapsed states as well as double tapping to hide. To
241+
use`BottomSheetDragHandleView`, you can add it to the top of your bottom sheet
242+
content. It will show a customizable visual indicator for all users. See the
243+
example in the below section for how to add a drag handle to your bottom sheet.
243244

244245
**Note:** `BottomSheetDragHandleView` has a default min width and height of 48dp
245246
to conform to the minimum touch target requirement. So you will need to preserve

lib/java/com/google/android/material/bottomsheet/BottomSheetDragHandleView.java

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@
2121
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_CLICKED;
2222
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2323

24+
import android.annotation.SuppressLint;
2425
import android.content.Context;
26+
import android.os.Handler;
27+
import android.os.Looper;
2528
import androidx.appcompat.widget.AppCompatImageView;
2629
import android.util.AttributeSet;
30+
import android.view.GestureDetector;
31+
import android.view.GestureDetector.OnGestureListener;
32+
import android.view.GestureDetector.SimpleOnGestureListener;
33+
import android.view.MotionEvent;
2734
import android.view.View;
2835
import android.view.ViewGroup.LayoutParams;
2936
import android.view.ViewParent;
3037
import android.view.accessibility.AccessibilityEvent;
31-
import android.view.accessibility.AccessibilityManager;
32-
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
3338
import androidx.annotation.NonNull;
3439
import androidx.annotation.Nullable;
3540
import androidx.coordinatorlayout.widget.CoordinatorLayout;
@@ -46,18 +51,25 @@
4651
* clickable. Clicking the drag handle will toggle the bottom sheet between its collapsed and
4752
* expanded states.
4853
*/
49-
public class BottomSheetDragHandleView extends AppCompatImageView
50-
implements AccessibilityStateChangeListener {
54+
public class BottomSheetDragHandleView extends AppCompatImageView {
5155
private static final int DEF_STYLE_RES = R.style.Widget_Material3_BottomSheet_DragHandle;
5256

53-
@Nullable private final AccessibilityManager accessibilityManager;
54-
5557
@Nullable private BottomSheetBehavior<?> bottomSheetBehavior;
5658

57-
private boolean accessibilityServiceEnabled;
58-
private boolean interactable;
59+
private final GestureDetector gestureDetector;
60+
5961
private boolean clickToExpand;
6062

63+
/**
64+
* Track whether clients have set their own touch or click listeners on the drag handle.
65+
*
66+
* Setting a custom touch or click listener will override the default behavior of cycling through
67+
* bottom sheet states when tapped and dismissing the sheet when double tapped. Clients can
68+
* restore this behavior by setting their touch and click listeners back to null.
69+
*/
70+
private boolean hasTouchListener = false;
71+
private boolean hasClickListener = false;
72+
6173
private final String clickToExpandActionLabel =
6274
getResources().getString(R.string.bottomsheet_action_expand);
6375
private final String clickToCollapseActionLabel =
@@ -75,6 +87,34 @@ public void onStateChanged(
7587
public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
7688
};
7789

90+
/**
91+
* A gesture listener that handles both single and double taps on the drag handle.
92+
*
93+
* Single taps cycle through the available states of the bottom sheet. A double tap hides
94+
* the sheet.
95+
*/
96+
private final OnGestureListener gestureListener = new SimpleOnGestureListener() {
97+
98+
@Override
99+
public boolean onDown(@NonNull MotionEvent e) {
100+
return isClickable();
101+
}
102+
103+
@Override
104+
public boolean onSingleTapConfirmed(@NonNull MotionEvent e) {
105+
return expandOrCollapseBottomSheetIfPossible();
106+
}
107+
108+
@Override
109+
public boolean onDoubleTap(@NonNull MotionEvent e) {
110+
if (bottomSheetBehavior != null && bottomSheetBehavior.isHideable()) {
111+
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
112+
return true;
113+
}
114+
return super.onDoubleTap(e);
115+
}
116+
};
117+
78118
public BottomSheetDragHandleView(@NonNull Context context) {
79119
this(context, /* attrs= */ null);
80120
}
@@ -83,17 +123,16 @@ public BottomSheetDragHandleView(@NonNull Context context, @Nullable AttributeSe
83123
this(context, attrs, R.attr.bottomSheetDragHandleStyle);
84124
}
85125

126+
@SuppressLint("ClickableViewAccessibility") // Will be handled by accessibility delegate
86127
public BottomSheetDragHandleView(
87128
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
88129
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
89130

90131
// Override the provided context with the wrapped one to prevent it from being used.
91132
context = getContext();
92133

93-
accessibilityManager =
94-
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
95-
96-
updateInteractableState();
134+
gestureDetector =
135+
new GestureDetector(context, gestureListener, new Handler(Looper.getMainLooper()));
97136

98137
ViewCompat.setAccessibilityDelegate(
99138
this,
@@ -112,25 +151,36 @@ public void onPopulateAccessibilityEvent(View host, @NonNull AccessibilityEvent
112151
protected void onAttachedToWindow() {
113152
super.onAttachedToWindow();
114153
setBottomSheetBehavior(findParentBottomSheetBehavior());
115-
if (accessibilityManager != null) {
116-
accessibilityManager.addAccessibilityStateChangeListener(this);
117-
onAccessibilityStateChanged(accessibilityManager.isEnabled());
118-
}
119154
}
120155

121156
@Override
122157
protected void onDetachedFromWindow() {
123-
if (accessibilityManager != null) {
124-
accessibilityManager.removeAccessibilityStateChangeListener(this);
125-
}
126158
setBottomSheetBehavior(null);
127159
super.onDetachedFromWindow();
128160
}
129161

162+
@SuppressLint("ClickableViewAccessibility") // Will be handled by accessibility delegate
163+
@Override
164+
public boolean onTouchEvent(MotionEvent event) {
165+
if (hasClickListener || hasTouchListener) {
166+
// If clients have set their own click or touch listeners, do nothing.
167+
return super.onTouchEvent(event);
168+
}
169+
170+
return gestureDetector.onTouchEvent(event);
171+
}
172+
173+
@SuppressLint("ClickableViewAccessibility")
174+
@Override
175+
public void setOnTouchListener(OnTouchListener l) {
176+
hasTouchListener = l != null;
177+
super.setOnTouchListener(l);
178+
}
179+
130180
@Override
131-
public void onAccessibilityStateChanged(boolean enabled) {
132-
accessibilityServiceEnabled = enabled;
133-
updateInteractableState();
181+
public void setOnClickListener(@Nullable OnClickListener l) {
182+
hasClickListener = l != null;
183+
super.setOnClickListener(l);
134184
}
135185

136186
private void setBottomSheetBehavior(@Nullable BottomSheetBehavior<?> behavior) {
@@ -144,7 +194,7 @@ private void setBottomSheetBehavior(@Nullable BottomSheetBehavior<?> behavior) {
144194
onBottomSheetStateChanged(bottomSheetBehavior.getState());
145195
bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallback);
146196
}
147-
updateInteractableState();
197+
setClickable(hasAttachedBehavior());
148198
}
149199

150200
private void onBottomSheetStateChanged(@BottomSheetBehavior.State int state) {
@@ -160,12 +210,8 @@ private void onBottomSheetStateChanged(@BottomSheetBehavior.State int state) {
160210
(v, args) -> expandOrCollapseBottomSheetIfPossible());
161211
}
162212

163-
private void updateInteractableState() {
164-
interactable = accessibilityServiceEnabled && bottomSheetBehavior != null;
165-
setImportantForAccessibility(bottomSheetBehavior != null
166-
? View.IMPORTANT_FOR_ACCESSIBILITY_YES
167-
: View.IMPORTANT_FOR_ACCESSIBILITY_NO);
168-
setClickable(interactable);
213+
private boolean hasAttachedBehavior() {
214+
return bottomSheetBehavior != null;
169215
}
170216

171217
/**
@@ -179,7 +225,7 @@ private void updateInteractableState() {
179225
* the previous state was EXPANDED) or EXPANDED (when the previous state was COLLAPSED.)
180226
*/
181227
private boolean expandOrCollapseBottomSheetIfPossible() {
182-
if (!interactable) {
228+
if (!hasAttachedBehavior()) {
183229
return false;
184230
}
185231
boolean canHalfExpand =

0 commit comments

Comments
 (0)