美文网首页
Flutter之Router和Navigator实现页面跳转

Flutter之Router和Navigator实现页面跳转

作者: 有没有口罩给我一个 | 来源:发表于2019-05-26 13:18 被阅读0次

    大多数应用程序都具有多个Page或View,并且希望将用户从当前Page平滑过渡到另一个页面。Flutter的路由和导航功能可帮助您管理应用中屏幕之间的命名和过渡。

    概述

    管理多个页面时有两个核心概念和类:Route和 Navigator。 一个route是一个屏幕或页面的抽象,Navigator是管理route的Widget。Navigator可以通过route入栈和出栈来实现页面之间的跳转。

    • 从First页面导航到second页面并返回FIrst页面:

        void main() => runApp(new MaterialApp(
        title: 'Navigation Basics',
        home: FirstRoute(),
        ));
      
        class FirstRoute extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(
        title: Text('First Route'),
        ),
        body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            // Navigate to second route when tapped.
            Navigator.of(context).push(new MaterialPageRoute(
                builder: (BuildContext context) => SecondRoute()));
          },
        ),
        ),
        );
        }
        }
      
        class SecondRoute extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(
        title: Text("Second Route"),
        ),
         body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to first route when tapped.
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
        ),
        );
        }
        }
      
    • 从A页面发送数据去B的页面,实际上是通过构造函数传递数据:

        class Todo {
            final String title;
            final String describe;
    
            Todo(this.title, this.describe);
        }
    
        class TodosScreen extends StatelessWidget {
                final List<Todo> todos;
    
                const TodosScreen({Key key, this.todos}) : super(key: key);
    
            @override
            Widget build(BuildContext context) {
            return new Scaffold(
                appBar: new AppBar(
                title: new Text('Todos'),
            ),
            body: new ListView.builder(
                itemCount: todos.length,
          itemBuilder: (BuildContext context, int index) {
            return new ListTile(
              title: new Text('todos[index].title'),
              onTap: () {
                Navigator.push(
                    context,
                    new MaterialPageRoute(
                        builder: (BuildContext context) => new DetailScreen(
                              todo: todos[index],
                            )));
              },
            );
          }),
        );
        }
        }
    
        class DetailScreen extends StatelessWidget {
                final Todo todo;
    
                const DetailScreen({Key key, this.todo}) : super(key: key);
    
        @override
        Widget build(BuildContext context) {
            return new Scaffold(
            appBar: new AppBar(
            title: new Text('${todo.title}'),
            ),
            body: new Padding(
            padding: EdgeInsets.all(16.0),
        child: new Text(todo.describe),
          ),
         );
        }
        }
    
    • 等待其他页面返回数据
        class HomeScreen extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(
        title: Text('Returning Data Demo'),
        ),
        body: Center(child: SelectionButton()),
        );
        }
        }
    
        class SelectionButton extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return RaisedButton(
        onPressed: () {
        _navigateAndDisplaySelection(context);
         },
        child: Text('Pick an option, any option!'),
        );
        }
    
        ///运行SelectionScreen页面并且等待SelectionScreen Navigator.pop!返回结果
        void _navigateAndDisplaySelection(BuildContext context) async {
        ///Navigator.push 将在我们调用SelectionScreen页面的Navigator.pop完成后返回一个携带结果数据Future
        final result =
        await Navigator.push(context, new MaterialPageRoute(builder: (context) {
         return SelectionScreen();
        }));
    
        //    String valResult = await result;
    
        ///之后等待SelectionScreen页面返回结果,隐藏任意上一个的SnackBars,并显示并将结果显示在SnackBar
        Scaffold.of(context)
            ..removeCurrentSnackBar()
            ..showSnackBar(new SnackBar(content: new Text(result)));
                 }
                }
    
        class SelectionScreen extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return new Scaffold(
        appBar: AppBar(
        title: Text('Pick an option'),
        ),
        body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // Close the screen and return "Yep!" as the result
                  Navigator.pop(context, 'Yep!');
                },
                child: Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // Close the screen and return "Nope!" as the result
                  Navigator.pop(context, 'Nope.');
                },
                child: Text('Nope.'),
              ),
            )
          ],
        ),
            ),
            );
        }
        }
    
    • 通过名字路由到其他页面
        void main() {
        runApp(MaterialApp(
        title: 'Named Routes Demo',
         // Start the app with the "/" named route. In our case, the app will start
         // on the FirstScreen Widget
         initialRoute: '/',
            routes: {
            // When we navigate to the "/" route, build the FirstScreen Widget
            '/': (context) => FirstScreen(),
            // When we navigate to the "/second" route, build the SecondScreen Widget
             '/second': (context) => SecondScreen(),
         },
        ));
        }
    
        class FirstScreen extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(
        title: Text('First Screen'),
            ),
            body: Center(
        child: RaisedButton(
          child: Text('Launch screen'),
          onPressed: () {
            // Navigate to the second screen using a named route
            Navigator.pushNamed(context, '/second');
          },
        ),
             ),
            );
        }
        }
    
        class SecondScreen extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
        appBar: AppBar(
        title: Text("Second Screen"),
            ),
            body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
            ),
         );
        }
        }
    
    • 跳转页面添加过度动画
        class HeroApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return MaterialApp(
        title: 'Transition Demo',
        home: MainScreen(),
        );
        }
        }
    
        class MainScreen extends StatelessWidget {
    
        @override
        Widget build(BuildContext context) {
            return Scaffold(
        appBar: AppBar(
        title: Text('Main Screen'),
        ),
        body: GestureDetector(
        child: Hero(
          tag: 'imageHero',
          child: Image.network(
            'http://pic37.nipic.com/20140113/8800276_184927469000_2.png',
          ),
        ),
    
        ///transitionsBuilder
        ///I/flutter (21575): pageBuilder
        ///I/flutter (21575): transitionsBuilder
        ///I/flutter (21575): transitionsBuilder
        ///I/flutter (21575): transitionsBuilder
        onTap: () {
          Navigator.push(
              context,
              new PageRouteBuilder(
                  transitionDuration: new Duration(seconds: 2),
                  transitionsBuilder: (BuildContext context,
                      Animation<double> animation,
                      Animation<double> secondaryAnimation,
                      Widget child) {
                    print('transitionsBuilder  这里会一直执行到动画结束');
        //                    return SlideTransition(
        //                      position: new Tween<Offset>(
        //                        begin: const Offset(0.0, 1.0),
        //                        end: Offset.zero,
        //                      ).animate(animation),
        //                      child: SlideTransition(
        //                        position: Tween<Offset>(
        //                          begin: Offset.zero,
        //                          end: const Offset(0.0, 1.0),
        //                        ).animate(secondaryAnimation),
        //                        child: child,
        //                      ),
        //                    );
    
                    return SlideTransition(
                      position: Tween<Offset>(
                        begin: const Offset(0.0, 1.0),
                        end: Offset.zero,
                      ).animate(animation),
                      child: child, // child is the value returned by pageBuilder
                    );
                  },
                  pageBuilder: (BuildContext context,
                      Animation<double> animation,
                      Animation<double> secondaryAnimation) {
                    print('pageBuilder');
                    return new DetailScreen();
                  }));
        },
        ),
        );
        }
        }
    
        class DetailScreen extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
        return Scaffold(
         body: GestureDetector(
        child: Center(
          child: Hero(
            tag: 'imageHero',
            child: Image.network(
              'http://pic37.nipic.com/20140113/8800276_184927469000_2.png',
            ),
          ),
        ),
        onTap: () {
          Navigator.pop(context);
        },
         ),
         );
        }
        }
    
    • 自定义Router

      class CustomRoute extends PageRouteBuilder {
        final Widget widget;
      
      CustomRoute(this.widget)
      : super(
            // 设置过度时间
            transitionDuration: Duration(seconds: 1),
            // 构造器
            pageBuilder: (
              // 上下文和动画
              BuildContext context,
              Animation<double> animaton1,
              Animation<double> animaton2,
            ) {
              return widget;
            },
            transitionsBuilder: (
              BuildContext context,
              Animation<double> animaton1,
              Animation<double> animaton2,
              Widget child,
            ) {
      //              旋转加缩放动画效果
              return RotationTransition(
                turns: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
                  parent: animaton1,
                  curve: Curves.fastOutSlowIn,
                )),
                child: ScaleTransition(
                  scale: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
                      parent: animaton1, curve: Curves.fastOutSlowIn)),
                  child: child,
                ),
              );
            });
      }
      

    使用很简单:

       final result =
        await Navigator.push(context, new CustomRoute(SelectionScreen()));
    
    //    String valResult = await result;
    
    ///之后等待SelectionScreen页面返回结果,隐藏任意上一个的SnackBars,并显示并将结果显示在SnackBar
    Scaffold.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(new SnackBar(content: new Text(result)));
    

    最后附上demo链接

    相关文章

      网友评论

          本文标题:Flutter之Router和Navigator实现页面跳转

          本文链接:https://www.haomeiwen.com/subject/bayxtctx.html