fujidaiti / smooth_sheets

Sheet widgets with smooth motion and great flexibility.
https://pub.dev/packages/smooth_sheets
MIT License
225 stars 22 forks source link

PopScope can not work when I drag down ModalSheetRoute in Flutter 3.24 #233

Closed Tommy-Wang0602 closed 2 months ago

Tommy-Wang0602 commented 2 months ago

hi ~ @fujidaiti I notice tutorial imperative_modal_sheet PopScopecan not work when I drag down ModalSheetRoute,expect will show dialog but doesn't

SDK version: Flutter 3.24.0 • channel stable • https://github.com/flutter/flutter.git Framework • revision 80c2e84975 (4 weeks ago) • 2024-07-30 23:06:49 +0700 Engine • revision b8800d88be Tools • Dart 3.5.0 • DevTools 2.37.2

video:

https://github.com/user-attachments/assets/42b674eb-7295-4e17-aaf8-80356ae007ea

  runApp(const _ImperativeModalSheetExample());
}

class _ImperativeModalSheetExample extends StatelessWidget {
  const _ImperativeModalSheetExample();

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: _ExampleHome(),
    );
  }
}

class _ExampleHome extends StatelessWidget {
  const _ExampleHome();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => _showModalSheet(context),
          child: const Text('Show Modal Sheet'),
        ),
      ),
    );
  }
}

void _showModalSheet(BuildContext context) {
  // Use ModalSheetRoute to show a modal sheet with imperative Navigator API.
  // It works with any *Sheet provided by this package!
  final modalRoute = ModalSheetRoute(
    // Enable the swipe-to-dismiss behavior.
    swipeDismissible: true,
    builder: (context) => const _ExampleSheet(),
  );

  Navigator.push(context, modalRoute);
}

class _ExampleSheet extends StatelessWidget {
  const _ExampleSheet();

  @override
  Widget build(BuildContext context) {
    // You can use PopScope to handle the swipe-to-dismiss gestures, as well as
    // the system back gestures and tapping on the barrier, all in one place.
    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) async {
        if (!didPop) {
          final shouldPop = await showConfirmationDialog(context);
          if (shouldPop == true && context.mounted) {
            Navigator.pop(context);
          }
        }
      },
      child: DraggableSheet(
        minExtent: const Extent.proportional(0.5),
        child: Card(
          color: Theme.of(context).colorScheme.secondaryContainer,
          margin: EdgeInsets.zero,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20),
          ),
          child: const SizedBox(
            height: 700,
            width: double.infinity,
          ),
        ),
      ),
    );
  }

  Future<bool?> showConfirmationDialog(BuildContext context) {
    return showDialog<bool>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: const Text('Are you sure?'),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context, true),
              child: const Text('Yes'),
            ),
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('No'),
            ),
          ],
        );
      },
    );
  }
}
fujidaiti commented 2 months ago

Hi @Tommy-Wang0602,

TL;DR

There are 2 options to work around this issue:

  1. Downgrade the Flutter SDK version to 3.22 or lower, or
  2. Fork the repo and replace this line with route.onPopInvokedWithResult(didPop, null);.

I'm planning to work on a solution soon...

Details

  1. The modal route uses the Route.onPopInvoked method to invoke the PopScope.onPopInvoked callback when the user swipes the sheet down to dismiss the modal.
  2. Flutter 3.24 has introduced a breaking change related to the PopScope widget, and PopScope.onPopInvoked is now deprecated.
  3. Accordingly, Route.onPopInvoked is also deprecated, and it no longer calls the PopScope.onPopInvoked callback (this is the reason why PopScope doesn't work with modals in the latest SDK).

As far as I know, the only solution is to replace Route.onPopInvoked with Route.onPopInvokedWithResult, which was newly added in Flutter 3.24. However, this solution forces package users to use the latest Flutter version, which is, of course, not ideal.

Tommy-Wang0602 commented 2 months ago

@fujidaiti Thank you for your response. May I also ask when approximately the next version will be released? Will this bug be resolved in the upcoming version?

fujidaiti commented 2 months ago

By this weekend, hopefully...

fujidaiti commented 2 months ago

@Tommy-Wang0602 Please follow to this guide: https://github.com/fujidaiti/smooth_sheets?tab=readme-ov-file#for-developers-using-flutter-324