等待页面转换完成

问题描述 投票:0回答:4

如何在 flutter 中检测页面转换是否完成?

背景:当我弹出一个页面时,我想在页面转换完成后启动一个功能。

flutter
4个回答
5
投票

当您

push
您的新路由也可以包含弹出路由中的数据时,您可以注册回调,例如,如果您需要从中传递数据。

Navigator.of(context).push(/*Some route*/).then((data) {
 // You can call your function here. data will be null if nothing is passed from the popped route
});

如果你想从弹出的路线中通过

data
,就这样吧

Navigator.of(context).pop(someData);

已编辑

如果你想知道转换实际上何时结束,你也可以为其注册一个回调监听器

  Navigator.of(context).push(MaterialPageRoute(
          builder: (BuildContext context) => RouteWidget())
                   ..completed.then((_) {print('transition completed');},
          ),
  );

4
投票

如果您保留对路线的引用并使用 didPush() TickerFuture,也可以等待推送转换

MaterialPageRoute route = MaterialPageRoute(builder: (context) => MyPage());
Navigator.of(context).push(route);
await route.didPush(); // you could also use then instead of await


// ROUTE FINISHED TRANSITION HERE 

如果您有多个堆叠导航器并且您希望它们之间的过渡更平滑,则可以使用此功能。就像等待导航器 1 完成推送后,再弹出当前活动的导航器 2 以显示导航器 1 的页面


2
投票

另一种解决方案

等待动画在第二页完成(如果你想在动画转换后更新页面,这很有用)

第一页:

...
Navigator.push(
        context,
        PageRouteBuilder(
            transitionDuration: Duration(milliseconds: 3000), //optional but useful for testing
            pageBuilder: (_, animation, ___) => SecondPage(
                  pageBuilderAnimation: animation,
                )));
...

第二页:

class SecondPage extends StatefulWidget {
  const SecondPage ({Key? key, this.pageBuilderAnimation});

  final Animation<double>? pageBuilderAnimation;

  @override
  _SecondPageState createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {

  bool isTransitioning = true;


  @override
  void initState() {
    super.initState();

    if (widget.pageBuilderAnimation != null)
      widget.pageBuilderAnimation!.addListener(() {
        if (widget.pageBuilderAnimation!.isCompleted)
          setState(() => isTransitioning = false);
      });
    else
      isTransitioning = false;
  }
  ...
}



0
投票

如果您需要回调来完成推送和弹出动画,只需使用路由的 animation 附加状态侦听器。

短:

route.animation?.addStatusListener((AnimationStatus status) {
  if (status.isCompleted) {
    print('push animation finished');
  } else if (status.isDismissed) {
    print('pop animation finished');
  }
});

flutter route animations callbacks

完整代码:

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;

void main() {
  timeDilation = 10.0; // slow down any animation
  runApp(DemoApp());
}

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        textTheme: const TextTheme(
          bodyMedium: TextStyle(fontSize: 20),
        ),
        elevatedButtonTheme: const ElevatedButtonThemeData(
          style: ButtonStyle(
            textStyle: WidgetStatePropertyAll(TextStyle(fontSize: 20)),
          ),
        ),
      ),
      home: PageOne(),
    );
  }
}

class PageOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Page one'),
            ElevatedButton(
              child: const Text('Open page two'),
              onPressed: () async {
                print('--------- open tap ---------');

                // 1. build route
                final route = MaterialPageRoute(builder: (_) => PageTwo());

                // 2. push route
                final routeFuture = Navigator.of(context).push(route);

                // 3. attach animation status listener
                route.animation?.addStatusListener((AnimationStatus status) {
                  if (status.isCompleted) {
                    print('push animation finished');
                  } else if (status.isDismissed) {
                    print('pop animation finished');
                  }
                });

                // 4. If you awaiting something from page two
                final result = await routeFuture;
                print('result: $result');
              },
            )
          ],
        ),
      ),
    );
  }
}

class PageTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Page two'),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).pop('Some data from page two');
              },
              child: const Text('Return result'),
            ),
          ],
        ),
      ),
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.