Home > Net >  How to know that a sheet has completely disappeared?
How to know that a sheet has completely disappeared?

Time:09-15

  1. Call the showMaterialModalBottomSheet(....)
  2. Click on scrim to make the sheet disappear
  3. If the showMaterialModalBottomSheet function is called with the await prefix,I can only be notified at the first frame when the sheet slide starts。How to know that a sheet has completely disappeared?

Please let me know if you know, thanks.

CodePudding user response:

Try showModalBottomSheet with whenComplete callback.

showModalBottomSheet<void>(
        builder: (context) => Container(),
).whenComplete(() {
// Goes here
});

CodePudding user response:

If you want to know when the output animation is finished you need to use an animation controller and attach it to the modalSheet.

late AnimationController _bottomSheetController;

After attaching the controller just listen to the animation status, when the sheet leaves the screen completely you will have the status dismissed.

@override
void initState() {
  super.initState();
  _bottomSheetController = AnimationController(
      vsync: this, duration: const Duration(milliseconds: 200))
    ..addStatusListener(_onListenerAnimation);
}

void _onListenerAnimation(AnimationStatus status) async {
  switch (status) {
    case AnimationStatus.dismissed:
      print('finished closing animation');
      break;
    case AnimationStatus.forward:
      print('starts opening sheet');
      break;
    case AnimationStatus.reverse:
      print('start closing the modal');
      break;
    case AnimationStatus.completed:
      print('finished opening animation');
      break;
  }
}

Using async/await or callback you would get the result the same time Navigator.of(context).pop() is triggered. But if you need to know exactly when sheet left the screen it would be using the controller.

FullCode

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(primarySwatch: Colors.blue),
        home: const MyStateFullWidget());
  }
}

class MyStateFullWidget extends StatefulWidget {
  const MyStateFullWidget({Key? key}) : super(key: key);

  @override
  State<MyStateFullWidget> createState() => _MyStateFullWidgetState();
}

class _MyStateFullWidgetState extends State<MyStateFullWidget>
    with TickerProviderStateMixin {
  late AnimationController _bottomSheetController;

  @override
  void initState() {
    super.initState();
    _bottomSheetController = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 200))
      ..addStatusListener(_onListenerAnimation);
  }

  @override
  void dispose() {
    super.dispose();
    _bottomSheetController
      ..removeStatusListener(_onListenerAnimation)
      ..dispose();
  }

  void _onListenerAnimation(AnimationStatus status) async {
    switch (status) {
      case AnimationStatus.dismissed:
        print('finished closing animation');
        break;
      case AnimationStatus.forward:
        print('starts opening sheet');
        break;
      case AnimationStatus.reverse:
        print('start closing the modal');
        break;
      case AnimationStatus.completed:
        print('finished opening animation');
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('Demo')),
        body: SizedBox.expand(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              TextButton(
                  onPressed: _openBottomSheet, child: const Text('Open sheet'))
            ],
          ),
        ));
  }

  void _openBottomSheet() {
    showModalBottomSheet(
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
      backgroundColor: Colors.white,
      context: context,
      transitionAnimationController: _bottomSheetController,
      isScrollControlled: false,
      builder: (context) {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: const Text('Pop')),
          ],
        );
      },
    );
  }
}

CodePudding user response:

You can always await for the return, I believe this is the most simple way to know if you are back from a BottomSheet or Page.

Example:

await showModalBottomSheet(
  context: context,
  builder: (context) => MyBottomSheet(),
);

doSomethinAfterAwait();
  • Related