material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.26k stars 3.06k forks source link

[BottomSheetDialogFragment] Top inset impossible to remove #3389

Open ParticleCore opened 1 year ago

ParticleCore commented 1 year ago

Description: I am currently trying to create a fullscreen/full height BottomSheetDialogFragment, but since it has a very weird behavior implemented where it adds and retracts insets while the sheet is sliding in and out, I decided to disable any inset handling done by the component and manually take care of the insets. However, I found a problem with that approach as well. No matter what I try, the component still forces a top inset that is the same size of the status bar even when disabling any and all inset handling flags I could find checked in the component source code, ex.:

https://github.com/material-components/material-components-android/blob/46778db594edc5915987dcd6e737fa7d15414690/lib/java/com/google/android/material/bottomsheet/BottomSheetBehavior.java#L1726-L1734

The objective is for the component screen to fill the entire screen of the device, but as it currently is the top area of the status bar can never be covered, meaning the component will never display underneath the status bar as desired.

Expected behavior: Screenshots are attached,

Source code: Not applicable.

Minimal sample app repro: Sample follows attached. BottomSheetInsetBug.zip

Android API version: Any android version since 24 (7.0 Nougat) till most recent 33 (13.0). Tested all versions and every single one of them have the same issue.

Material Library version: Material Android Library version com.google.android.material:material:1.8.0

Device: Any real device and emulator tested.

imhappi commented 1 year ago

I don't believe we want to remove the top inset for the bottom sheet, as content could get cut off eg. on devices with front cameras overlaying the screen

However, you should be able to achieve getting the bottom sheet under a transparent status bar, which would make it the same color as the bottom sheet.

See this example of a full-screen bottom sheet that goes under the status bar can be found on our test app: https://github.com/material-components/material-components-android/blob/master/catalog/java/io/material/catalog/bottomsheet/BottomSheetMainDemoFragment.java

ParticleCore commented 1 year ago

@imhappi

Please reopen, that is not the same thing as I was pointing out. I did explain that I was trying to achieve this because the current implementation of the component is adding the insets in a dynamic way which causes any content inside of it to squeeze and stretch (as long as the view height is set to match_parent) as the user slides the component up or down. As that happens, the top and bottom insets are being incremented/decremented as the component slides vertically.

That is the main reason why I wanted to just turn off that entire behavior completely and handle it manually, but even when I do that the component is permanently adding a top inset which cannot be disabled by any available option.

ParticleCore commented 1 year ago

Here is a quick video example showing the issue with using the default inset handling in the component.

1

And the modified sample attached (mostly disabling the style padding inset attributes, the rest was just changed to make it easier to see in the recording above). BottomSheetInsetBug2.zip

Please pay attention to what is happening to the top and bottom of the content of the sheet as I try to slide down and up, you will notice the view height increases and decreases before any movement takes place. I am not doing that, the BottomSheetDialogFragment is doing that automatically.

I believe this happens because the component is adding/removing insets in the main view in order to offset the content as the view slides in and out of a position that overlaps the top and bottom insets.

This causes any child inside with a height set to match_parent to stretch and shrink without any other way to disable this behavior.

That is why I was trying the other option, to simply NOT use any inset padding automatically and instead do it manually, but as I documented above even that is being forced with no way to prevent it.

To summarize, it is currently impossible to have a true edge to edge BottomSheetDialog that does not mess with the height or prevents the content to scroll to the top.

The reason why I want the view height to be match_parent is because it can change height, which means sometimes it might not have enough content for the entire view to fill the screen, and sometimes does (even just display/zoom settings can affect this), and my goal is to have a standard sheet that is always the same size (full height) with dynamic content inside.

ParticleCore commented 1 year ago

Unsure if this is gonna be ignored because it was closed, so I will open a new issue with the extra details further explained which were clearly missed. If not necessary then reopen this one and close the other one as duplicate.

ParticleCore commented 1 year ago

@imhappi thanks for reopening, I wasn't sure if this repo was set to ignore closed cases or not.

oOJohn6Oo commented 1 year ago

I think you are not using it in a right way, try the style below.

<style name="MyModalBottomSheetDialog" parent="@style/Theme.MaterialComponents.BottomSheetDialog">
    <item name="enableEdgeToEdge">true</item>
    <item name="android:windowIsFloating">false</item>
    <item name="paddingBottomSystemWindowInsets">false</item>
    <item name="paddingTopSystemWindowInsets">false</item>
</style>
oOJohn6Oo commented 1 year ago

I think you are not using it in a right way, try the style below.

<style name="MyModalBottomSheetDialog" parent="@style/Theme.MaterialComponents.BottomSheetDialog">
    <item name="enableEdgeToEdge">true</item>
    <item name="android:windowIsFloating">false</item>
    <item name="paddingBottomSystemWindowInsets">false</item>
    <item name="paddingTopSystemWindowInsets">false</item>
</style>

Oh sorry, it's not work. That's truly a bug. But I do have a way to prevent BottomSheet's weird behavior.

  1. Override DialogFragment's onViewCreated function.
  2. Set a WindowInsetsListener to android.R.id.content, and consume all insets.

    ViewCompat.setOnApplyWindowInsetsListener(desiredView) { _, insets ->
    // customize your view here
    
    WindowInsetsCompat.CONSUMED
    }
ParticleCore commented 1 year ago

I think you are not using it in a right way, try the style below.

<style name="MyModalBottomSheetDialog" parent="@style/Theme.MaterialComponents.BottomSheetDialog">
    <item name="enableEdgeToEdge">true</item>
    <item name="android:windowIsFloating">false</item>
    <item name="paddingBottomSystemWindowInsets">false</item>
    <item name="paddingTopSystemWindowInsets">false</item>
</style>

Oh sorry, it's not work. That's truly a bug. But I do have a way to prevent BottomSheet's weird behavior.

1. Override DialogFragment's `onViewCreated` function.

2. Set a WindowInsetsListener to android.R.id.content, and consume all insets.
ViewCompat.setOnApplyWindowInsetsListener(desiredView) { _, insets ->
    // customize your view here

    WindowInsetsCompat.CONSUMED
}

Thanks for the suggestion, but then the rest of the app will no longer receive the insets, and to work around that you have to create your own inset manager and it becomes a complete nightmare. So far the best compromise I found was to make the height a static value by calculating exactly how tall it should be when fully opened, but this might break in the future I believe.

bharat1320 commented 5 months ago

Guys this worked like a charm for me, // Set dialog to full-screen, removing the top insets for notification bar // Set it in onStart() dialog?.window?.apply { setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS ) }