I have a plain old `BottomSheetDialogFragment` (ca...
# compose
s
I have a plain old
BottomSheetDialogFragment
(can’t change that to Compose unfortunately), which contains a
LazyColumn
. I am kind of stuck figuring out, why the scrolling does not work as expected, e.g. why the
BottomSheetDialogFragment
intercepts the
LazyColumn
scrolling. Is there any flag / setting / modifier for
LazyColumn
regarding nested scrolling, that I am missing? Expected behaviour would be that I can drag the Sheet down as soon as I have scrolled up completely, but not before. Cannot convert it to a
Column
though, since the items need to be lazy loaded. 👉 Video attached in 🧵. Any ideas welcomed. Thank you!
w
I encountered this issue as well. BottomSheet has a method that it calls on the View class to identify if the class is scrollable. Compose does not implement this class, so unfortunately nested scrolling is not functional. I tried for about a day to find a workaround, but in the end did not find any. I ended up needing to implement my own, which subclassed DialogFragment and set a Compose scaffold as its content.
It was one of my first experiences with Compose. 🙂 I will say, implementing the Nested scrolling behavior was so much easier in compose than in the old system!
here’s a super quick idea of what it looks like (I removed all our custom classes, so it might not work out of the box- you’ll probably need to make some adjustments)
Copy code
class ComposeBottomSheetDialogFragment(
    val sheetContent: @Composable ColumnScope.() -> Unit
) : DialogFragment() {
    private var onDismissListener: (() -> Unit)? = null

    @OptIn(ExperimentalMaterialApi::class)
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        super.onCreateView(inflater, container, savedInstanceState)
        setStyle(STYLE_NO_FRAME, R.style.FullScreenDialog)
        dialog?.let {
            val width = ViewGroup.LayoutParams.MATCH_PARENT
            val height = ViewGroup.LayoutParams.MATCH_PARENT
            it.window?.setLayout(width, height)
            it.window?.setBackgroundDrawable(ColorDrawable(resources.getColor(R.color.transparent)))
        }

        return inflater.inflate(R.layout.fragment_checkout_landing_screen, container, false).apply {
            this.findViewById<ComposeView>(R.id.compose_view).apply {
                setContent {
                     // your content
                }
            }
        }
    }

    override fun getTheme() = R.style.FullScreenDialog

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        onDismissListener?.invoke()
    }

    fun setOnDismissListener(function: () -> Unit) {
        this.onDismissListener = function
    }
}
and here is the theme:
Copy code
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="FullScreenDialog" parent="Theme.AppCompat.Light.Dialog">
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:padding">0dp</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowCloseOnTouchOutside">false</item>
    </style>
</resources>
note that some of this might be unnecessary for you.
s
Hey @Will Shelor , awesome, thanks for taking your time 🙏 As I see it, this will then not allow swipe to dismiss, correct? So you would only be able to explicitely close the dialog via button, etc? Actually that is something I want to avoid. 🤔 I have also played around with
isCancelable
in the BottomSheetDialogFragment…. But swipe to dismiss is nice and I would like it to keep, if I can.
It was one of my first experiences with Compose.
Yeah feels like learning something new everyday again 😆
w
ha! You’ve gotten into complicated territory! We made a custom bottom sheet for just this reason. We copied the base idea of the accompanist bottom sheet scaffold and made our own with some custom behavior. It was a great introduction to the concepts of what compose does
🔥 1
🤔 1
s
Update: I got at least the BottomSeetDialogFragment to not intercept my touch event with this Modifier here - but then my
LazyColumn
denies scrolling… But I feel I might have to dig deeper there, “halfway there”:
Copy code
val lazyListState = rememberLazyListState()
val disallow = RequestDisallowInterceptTouchEvent()

LazyColumn(
    modifier = Modifier
        .pointerInteropFilter(requestDisallowInterceptTouchEvent = disallow, onTouchEvent = {
            when(it.action) {
                MotionEvent.ACTION_DOWN -> {
                    disallow(true)
                    return@pointerInteropFilter true
                }
                MotionEvent.ACTION_UP -> {
                    disallow(false)
                    return@pointerInteropFilter false
                }
            }
            true
        })
        .fillMaxWidth(),
    state = lazyListState
) {
.... items content
We made a custom bottom sheet for just this reason. We copied the base idea of the accompanist bottom sheet scaffold and made our own with some custom behavior.
So it keeps being swipe to dismissable? Mind to share some insights in how you tackled the nested scrolling part in the custom behavior? Probably would make a good stackoverlfow answer as well 😄
w
I added a quick version of this discussion to that question; it’d be tough without open sourcing it because there is so much required, and I’m not 100% sure it’s ready for it 😆 it’s pretty custom to our application at this point
🙏 1
s
There is a method on View called isNestedScrollingEnabled(), and Compose always returns false,
Mind if I ask where you found that call, and that compose returns false? Maybe subclassing
ComposeView
(like with those old ViewPager hacks to allow nested scrolling) would be worth looking into 🤔.
But then again, probably its easier to change my requirements 😬
I figured the
RequestDisallowInterceptTouchEvent
could be a lead, but no luck for now. I feel I’ll have to read myself back in touch event internals.
w
I found isNestedScrollingEnabled in BottomSheetBehavior in the Material library, line 1210, after a day of walking through and trying to figure out why it didn’t like my compose view as a nested scroll target. I also hunted for a way down the path you’re talking about here. I tried 6 or 7 things when I just decided to convert the whole thing to Compose. Our research found that was better for performance anyways, so it wasn’t a hard sell to the team. 🙂