美文网首页Flutter学习日记Flutter圈子
Flutter 学习笔记 10 - 路由和导航(2)

Flutter 学习笔记 10 - 路由和导航(2)

作者: 三流之路 | 来源:发表于2019-01-05 18:32 被阅读5次

返回数据

如果要返回数据,pop 方法还有一个重载方法,有个可选的位置参数,用于传递返回的数据。

static bool pop<T extends Object>(BuildContext context, [ T result ]) {
  return Navigator.of(context).pop<T>(result);
}

比如 Navigator.pop(context, "返回内容");,然后将 push 放到异步函数里,返回值就是其它页面返回的 result。

class FirstScreen extends StatelessWidget {

  // 异步函数
  _toSecond(BuildContext context) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SecondScreen(title: "标题", content: "内容")),
    );
    
    // 等待页面返回,数据存为 result
    print('result=$result');
    Scaffold.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(SnackBar(content: Text("$result")));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('content'),
          onPressed: () {
            _toSecond(context);
          },
        ),
      ),
    );
  }
}

结果日志打印出来了,但是 SnackBar 未显示,看错误日志以及官网有效的代码,发现要把 FirstScreen 这个 widget 放到 Scaffold 的 body 位置才行,SnackBar 的 Scaffold.of(context) 参数有问题。

尝试将 FirstScreen 改成 StatefulWidget。

class FirstScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return FirstState();
  }
}

class FirstState extends State<FirstScreen> {
  int count = 0;
  var content = 'content';
  _toSecond(BuildContext context) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SecondScreen(title: "标题", content: "内容${++count}")), // 每次传递的内容有变化
    );

    // 当从其它页面返回时,重新设置 content 以让当前页面发生变化
    setState(() {
      content = result;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          // 使用 content 变量内容,从其它页面返回时会发生变化
          child: Text('$content'),
          onPressed: () {
            _toSecond(context);
          },
        ),
      ),
    );
  }
}

然后修改 SecondScreen,返回传进来的值。

class SecondScreen extends StatelessWidget {
  final String title;
  final String content;

  // 构造方法接收两个参数
  SecondScreen({Key key, @required this.title, @required this.content}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // 返回传进来的内容
            Navigator.pop(context, "返回$content");
          },
          child: Text(content),
        ),
      ),
    );
  }
}
2019_01_05_10_32_54.gif

通过给 route 命名来跳转

MaterialApp(
  // initialRoute 表示当前要显示的内容
  initialRoute: '/',
  routes: {
    // 根路径表示 FirstScreen
    '/': (context) => FirstScreen(),
    '/second': (context) => SecondScreen(),
  },
);

测试发现必须要在 MaterialApp 里用,initialRoute 表示要显示的内容,不允许写 home 了

页面跳转时使用

Navigator.pushNamed(context, '/second');
// 代替下面的写法
// Navigator.push(
//   context,
//   MaterialPageRoute(builder: (context) => FirstScreen()),
// );

返回依然用 Navigator.pop 方法。

在不同页面对一个 Widget 做动画

类似 Android 的转场动画

将两个页面都要显示的 Widget 用 Hero 这个 Widget 包裹一层。

Hero(
  tag: 'imageHero',
  child: Image.network(
    'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
  ),
);

在两个页面 tag 必须一样,child 是要做动画的内容。

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(
            'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
          ),
        ),
        onTap: () {
          Navigator.push(context, MaterialPageRoute(builder: (_) {
            return DetailScreen();
          }));
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        child: Center(
          child: Hero(
            tag: 'imageHero',
            child: Image.network(
              'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
            ),
          ),
        ),
        onTap: () {
          Navigator.pop(context);
        },
      ),
    );
  }
}

第一个页面中图片在上边,到了第二个页面,图片到了中间。

2019_01_05_18_17_27.gif

修改第二个页面的图片大小

child: Hero(
  tag: 'imageHero',
  child: Container(
    height: 100,
    margin: const EdgeInsets.symmetric(horizontal: 10.0),
    child: Image.network(
      'https://raw.githubusercontent.com/flutter/website/master/src/_includes/code/layout/lakes/images/lake.jpg',
    ),
  )
),
2019_01_05_18_22_01.gif

相关文章

  • Flutter 学习笔记 10 - 路由和导航(2)

    返回数据 如果要返回数据,pop 方法还有一个重载方法,有个可选的位置参数,用于传递返回的数据。 比如 Navig...

  • flutter 导航以及传参方式

    flutter 导航方式有基本路由和命名路由1、基本路由 ============================...

  • Flutter—— 路由(Route)和导航(Navigator

    Flutter的页面,怎么进行跳转的呢?通过路由和导航呢。 一、路由和导航,初认识 言简意赅! 路由(Route)...

  • flutter_boost

    混合开发要点 flutter engine复用 flutter路由和原生导航同步 flutter和原生数据传输->...

  • Flutter 学习笔记 09 - 路由和导航(1)

    管理多个页面时有两个核心概念和类:Route 和 Navigator。 Route 是一个屏幕或页面的抽象 Nav...

  • Flutter 路由和导航

    大部分应用程序都包含多个页面,并希望用户能从当前屏幕平滑过渡到另一个屏幕。移动应用程序通常通过被称为“屏幕”或“页...

  • Flutter路由和导航

    管理多个页面时有两个核心概念和类:Route和 Navigator。 一个Route是一个屏幕或页面的抽象,Nav...

  • 8. 【文档讲解】路由与导航

    3-14 【文档讲解】路由与导航 路由与导航 Flutter中Intent等价于什么?(Android) 在Flu...

  • flutter路由

    在Flutter中,导航器管理应用程序的路由栈。将路由推入(push)到导航器的栈中,将会显示更新为该路由页面。 ...

  • Flutter路由使用指北

    路由管理 FLutter中的路由,和原生组件化的路由一样,就是页面之间的跳转,也可以称之为导航。app维护一个路由...

网友评论

    本文标题:Flutter 学习笔记 10 - 路由和导航(2)

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