material-components / material-components-android

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

[BottomSheet] Padding for status bar not applied when starting expanded #2165

Closed Slion closed 2 years ago

Slion commented 3 years ago

Description: Top padding for status bar not applied when starting expanded with edge-to-edge. The content view is then drawn below our transparent status bar. If you start sliding the bottom sheet the padding get set properly.

Expected behavior: Top padding should be applied even when starting expanded.

Source code: Assuming edge to edge attribute is set to true and transparent status bar:

    val bottomSheetDialog = BottomSheetDialog(this)
    // We need to set private data member edgeToEdgeEnabled to true to get full screen effect
    // That has been already fixed since alpha 02 release, this is not our issue here but was left for completeness 
    val field = BottomSheetDialog::class.java.getDeclaredField("edgeToEdgeEnabled")
    field.isAccessible = true
    field.setBoolean(bottomSheetDialog,true)
    //
    bottomSheetDialog.setContentView(myView)
    bottomSheetDialog.show()
    bottomSheetDialog.behavior.skipCollapsed = true
    bottomSheetDialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED

To workaround that issue I had to:

    mainHandler.postDelayed( {
        bottomSheetDialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    },100)

Analysis ̀EdgeToEdgeCallback.setPaddingForPosition is not getting called when setting the state to expanded just after the call to show. For some reason ̀EdgeToEdgeCallback.onStateChanged is not called then. Moreover if the content of the sheet changes causing it to change its size the padding can get out of sync. Like showing top padding when none needed because sheets got smaller or not showing the padding when needed because sheet got bigger. ̀EdgeToEdgeCallback.setPaddingForPosition should also be called whenever the sheet size is changed.

Android API version: 28

Material Library version: 1.4.0-alpha02

Device: F(x)Tec Pro¹

Slion commented 3 years ago

Also if you set the state to expanded before showing your dialog you don't get any onStateChanged call.

Slion commented 3 years ago

This is also somewhat related to #2168

Slion commented 3 years ago

Here is what I did to workaround those issues. Just calling that function whenever the bottom sheet size changes does the trick:

/**
 * To fix issues with wrong edge-to-edge bottom sheet top padding and status bar icon color…
 * …we need to call [BottomSheetDialog.EdgeToEdgeCallback.setPaddingForPosition] which is a private function from a private class.
 * See: https://github.com/material-components/material-components-android/issues/2165
 */
fun adjustBottomSheet(aDialog : BottomSheetDialog) {
    // Get our private class
    val classEdgeToEdgeCallback = Class.forName("com.google.android.material.bottomsheet.BottomSheetDialog\$EdgeToEdgeCallback")
    // Get our private method
    val methodSetPaddingForPosition: Method = classEdgeToEdgeCallback.getDeclaredMethod("setPaddingForPosition", View::class.java)
    methodSetPaddingForPosition.isAccessible = true
    // Get private field containing our EdgeToEdgeCallback instance
    val fieldEdgeToEdgeCallback = BottomSheetDialog::class.java.getDeclaredField("edgeToEdgeCallback")
    fieldEdgeToEdgeCallback.isAccessible = true
    // Get our bottom sheet view field
    val fieldBottomField = BottomSheetDialog::class.java.getDeclaredField("bottomSheet")
    fieldBottomField.isAccessible = true
    // Eventually call setPaddingForPosition from EdgeToEdgeCallback instance passing bottom sheet view as parameter
    methodSetPaddingForPosition.invoke(fieldEdgeToEdgeCallback.get(aDialog),fieldBottomField.get(aDialog))
}
OscarSpruit commented 3 years ago

Any updates on this? Having the same problem and the original workaround isn't looking pretty and it isn't working in every case.

Slion commented 3 years ago

Any updates on this?

Check the Fulguris source code maybe I'm pretty sure it is still working there somehow.

Slion commented 2 years ago

Could it be that this was fixed somewhat in v1.4.0?

durkester commented 2 years ago

Still having this problem, couldn't get the workaround to even work.

drchen commented 2 years ago

I have a fix just merged internally. Should be copied over here very soon if everything looks fine.