Reduces and restructures the calling chain when a state is set to improve readability and robustness.
This CL also introduces the following fixes:
1. Limit the possible input values of setState() and throws IllegalArgumentException if invalid values are provided.
2. Block the state to be set as HIDDEN when hideable is false.
3. Fix the bug that SettleRunnable could be posted multiple times due to isPosted flag being incorrectly set to false when the settling is still going on.
4. Fix the bug that dragging the bottom sheet when settling would result the bottom sheet in an incorrect state (the target state of settling instead of DRAGGING).
PiperOrigin-RevId: 432963533
The activity leak can happen in a corner case: setting bottom sheet state when the bottom sheet is dismissed and the host activity is closed. In this situation SettleRunnable will be posted to ViewRootImpl since the bottom sheet is not attached, which leaves references of the dismissed bottom sheet (and thus the destroyed activity) in ViewRootImpl and causes activity leak.
Fixes this by using weak reference in SettleRunnable instead of the strong reference, which is the standard practice of the BottomSheetBehavior class.
Resolves https://github.com/material-components/material-components-android/issues/1417
PiperOrigin-RevId: 430709002
Since adding bottom sheet behavior callbacks won't trigger any callbacks to be called, the bottom sheet paddings won't be updated right away. This causes the issue that top paddings are not correctly applied when the bottom sheet is initially expanded. Besides that, due to some unknown reason, bottom sheet's getTop() method will only return a non-zero value that is the offset to the container top when calling from bottom sheet behavior callbacks. It seems related to how ViewCompat.offsetTopAndBottom() is working. Not 100% sure.
Therefore this CL add a internal callback to BottomSheetCallback class so when bottom sheet is being laid out (and getting offset), we can update paddings right away.
Resolves https://github.com/material-components/material-components-android/issues/2165
PiperOrigin-RevId: 429071367
Previously the BottomSheetBehavior was checking the measured size during onLayout and if it exceeded the max width or height configured it would "adjust" them by directly modifying the width and height on the layout params and then posting a setLayoutParams. This has many problems and is fundamentally the wrong way to do it. First off, a view should never modify the layout params that are configured on it for two reasons, one, they are properties of the parent view group, not the view itself, and two, they are almost always intended for users of the view group to configure, not the view group itself. Modifying the layout params directly is clobbering any previously configured parameter and permanently changing the layout (for example consider the case where the max width is set to 100dp and then later set to 200dp, the view would not be allowed to grow to 200dp because its layout params would already have been clobbered). Secondly the post is a very bad way to apply this max, not only does it trigger an entire layout pass a second time but it does so after having completed the first layout pass so it will cause the bottom sheet to render at the original size and then the capped size, it's both inefficient and will cause user visible jank.
The correct way to apply a maximum width/height is to do it during layout by incorporating it into the measure specs that are passed to the child. This doesn't clobber any state that the user of the view configured (i.e. when the parent measure specs change, e.g. due to screen rotation, the views correctly relayout) and it avoids doing multiple layout passes, the child can measure itself to the correct size the first time.
PiperOrigin-RevId: 387379138
When BottomSheetBehavior is set to not draggable, it's still forwarding touch event to ViewDragHelper, which causes ViewDragHelper changes its state to dragging although it's not really dragging. This causes bugs like if we change draggable to true during "no-effect" dragging, ViewDragHelper won't report the dragging state change because it thinks the state is not changing.
Fixes this by avoiding forwarding touch events to ViewDragHelper when it's not draggable, so its state won't be changed.
Resolves https://github.com/material-components/material-components-android/issues/2258
PiperOrigin-RevId: 384942764
The DialogFragment will set the content view during the INITIALIZED state of the Lifecycle. This happens prior to onCreate and currently results in the edgeToEdgeEnabled value always being false at the time the OnApplyWindowInsertListener is conditionally set.
PiperOrigin-RevId: 366294759
Because the BottomSheet could be shown under the navigation bar if it's transparent or translucent, it's best to ensure insets are added. If no insets are added, views can end up behind the navigation bar which prevents any interaction.
PiperOrigin-RevId: 348470697