Flutter之Router和Navigator实现页面跳转

2019-05-26  本文已影响0人  有没有口罩给我一个

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

概述

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

    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);
    },
     ),
     );
    }
    }

使用很简单:

   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链接

上一篇 下一篇

猜你喜欢

热点阅读