woltapp / wolt_modal_sheet

This package provides a responsive modal with multiple pages, motion animation for page transitions, and scrollable content within each page.
MIT License
477 stars 63 forks source link

Custom top bar widget not receiving any click events due to Stack layout its placed #180

Open ndasim opened 5 months ago

ndasim commented 5 months ago

Bug report

I've implemented a custom top bar widget with a close button according to our design guidelines. However, I've encountered an issue where the close button functionality is disabled. It appears that the top bar widget is placed underneath the drag handler widget within the stack layout. This positioning prevents the close button from registering click events.

Here you can see that my top bar placed in that Animated Builder and the next Positioned widget holds WoltBottomSheetDragHandle causes top widget to not detect clicks

image

The relation between stack and gesture detector is well known issue in the community, you can see related issue from here: https://github.com/flutter/flutter/issues/75747

One possible solution is using defer pointer as suggested in the issue I metioned, however its not possible without touching source code of WoltModalSheetLayout since it requires wrapping DeferredPointerHandler above the Stack widget.

I'm seeking for your suggestion or any help to continue.

If there are any way of implementing custom close button with positioning it would help also. I tried setting trailingNavBarWidget but there is no luck, it didn't show up with custom top bar widget.

Steps to reproduce

Set topBar widget on the WoltModalSheetPage with custom action button, you will notice that action will not be clickable.

Expected behavior

Custom top bar widget must be able to receive click events.

ulusoyca commented 5 months ago

Hi @ndasim Thanks for the report! Do you think that you can create a PR?

ndasim commented 5 months ago

Sure, but I have some questions about using defer pointer for such library, even you documentate it well, very few of us will use defer pointer correctly to detect clicks. I think there must be workaround on the WoltBottomSheetDragHandle. Today I will find a better way and push my pull request.

ndasim commented 5 months ago

@ulusoyca I simply changed placement of drag handlers' GestureDetector to allow top bar receive gesture events, please see pr: https://github.com/woltapp/wolt_modal_sheet/pull/181

ulusoyca commented 4 months ago

Hi @ndasim I am really sorry for the late response. Thanks for the detailed explanation and the PR. I am having a little bit difficulty to understand the case with your custom top bar. Can you please provide a very simple reproducible project with your custom top bar?

ulusoyca commented 4 months ago

This is how the gesture detector of the modal sheet drag handle is placed:

image

Placing the close button in the playground app certainly doesn't block the close button.

ndasim commented 3 months ago

Hi @ulusoyca, we are using a wrapped version of AppBar for showing the custom app bar on our side. And since the enableDrag attribute puts DeferredPointerHandler into the front of this custom app bar, it disables receiving click events in our custom app bar widget. Here you can see the minimum reproducible code which shows the same issue.

I tried this code on latest wolt_modal_sheet.

class ShowBottomSheet extends StatelessWidget {
  const ShowBottomSheet({super.key});

  @override
  Widget build(BuildContext context) {
    final page = NonScrollingWoltModalSheetPage(
      topBar: AppBar(
        primary: false,
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 8),
            child: IconButton(
              icon: const Icon(Icons.close),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
          )
        ],
      ),
      hasTopBarLayer: true,
      navBarHeight: kToolbarHeight,
      child: const Center(
        child: Text("The body"),
      ),
    );

    return Scaffold(
      body: Center(
        child: ElevatedButton(
          child: const Text("Show it"),
          onPressed: () {
            WoltModalSheet.show(
              context: context,
              pageListBuilder: (modalSheetContext) {
                return [
                  page,
                ];
              },
            );
          },
        ),
      ),
    );
  }
}
ABausG commented 3 months ago

@ndasim I faced the exact same Issue (just with a custom AppBar instead of Material)

I could solve it easily by doing:

WoltModalSheetPage(
        topBar: const SizedBox.shrink(),
        // Set Modal Header as Leading to be above drag Handle
        leadingNavBarWidget: modal.header,
        hasTopBarLayer: true,

instead of

WoltModalSheetPage(
        topBar: modal.header,
        hasTopBarLayer: true,