10天学会flutter DAY8 flutter 玩转路由与导航

本文详细介绍了如何在Flutter应用中使用Navigator进行页面间导航,以及处理动画效果(如FadeTransition和RotationTransition)。还探讨了在使用Navigator时遇到的问题,提供了解决方案,包括使用Builder和navigatorKey。此外,文章还提及了如何集成WebView和提供系统化学习资源的重要性。
摘要由CSDN通过智能技术生成

)

],

),

);

}

}

同时我们也可以对动画进行组合

import ‘package:flutter/material.dart’;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: ‘Flutter Demo’,

home: MainRoute(),

);

}

}

class MainRoute extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(“主页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () async {

//导航到新路由

var result = await Navigator.push(

context,

PageRouteBuilder(

///动画时间

transitionDuration: Duration(milliseconds: 500),

pageBuilder: (BuildContext context, Animation animation,

Animation secondaryAnimation) {

///透明渐变与旋转

return new FadeTransition(

opacity: animation,

child: new RotationTransition(

turns: new Tween(begin: 0.5, end: 1.0)

.animate(animation),

child: SecondRoute(),

),

);

},),

);

debugPrint(“返回:$result”);

},

child: Text(“进入第二页”),

)

],

),

);

}

}

class SecondRoute extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(“第二页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

//路由pop弹出

Navigator.pop(context, “结束”);

},

child: Text(“返回”),

)

],

),

);

}

}

注意点

import ‘package:flutter/material.dart’;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: ‘Flutter Demo’,

home: Scaffold(

appBar: AppBar(

title: Text(“主页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

///Navigator.push内部其实就是 Navigator.of(context).push

Navigator.of(context).push(MaterialPageRoute(builder: (_){

return new SecondRoute();

}));

},

child: Text(“进入第二页”),

)

],

),

),

);

}

}

class SecondRoute extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(“第二页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

//路由pop弹出

Navigator.pop(context);

},

child: Text(“返回”),

)

],

),

);

}

}

这段代码运行会出现错误:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nTsm3fZH-1652166110875)(图片\路由异常.png)]

​ 问题关键点在于Navigator operation requested with a context that does not include a Navigator.(导航操作请求使用了不包含Navigator的上下文context)

Navigator实际上也是一个Widget,这个异常出现在Navigator.of(context)路由器的获取上,而这句代码会从当前的context的父级一层层向上去查找一个Navigator,我们当前传递的context就是MyApp,它的父级是root——UI根节点。Navigator这个widget的并不是由root创建的,因此在root下一级的上下文中无法获得Navigator

在之前所有的路由案例中,我们的上下文是MainRoute,它的父级是MaterialApp。MaterialApp内部就会创建一个Navigator。

MaterialApp->_MaterialAppState->WidgetsApp->_WidgetsAppState

​ 所以问题就在于,Navigator需要通过MaterialApp或者它孩子的上下文。

解决一

按照此笔记最开始的正常路由演示案例来进行修改。

解决二

使用Builder

import ‘package:flutter/material.dart’;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: ‘Flutter Demo’,

home: Scaffold(

appBar: AppBar(

title: Text(“主页”),

),

body: Column(

children: [

Text(“第一个页面”),

///

Builder(builder: (context){

return RaisedButton(

onPressed: () {

Navigator.of(context).push(MaterialPageRoute(builder: (_){

return new SecondRoute();

}));

},

child: Text(“进入第二页”),

);

})

],

),

),

);

}

}

class SecondRoute extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(“第二页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

//路由pop弹出

Navigator.pop(context);

},

child: Text(“返回”),

)

],

),

);

}

}

​ 使用Builder嵌套,Builder的参数可以看成一个回调,接收自身的context并返回布局配置。现在路由是从Builder的父亲开始查找啦,自然能找到Navigator。

解决三

使用navigatorKey

import ‘package:flutter/material.dart’;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

final GlobalKey navigatorKey = GlobalKey();

@override

Widget build(BuildContext context) {

return new MaterialApp(

///指定路由器widget的key

navigatorKey: navigatorKey,

title: ‘Flutter Demo’,

home: Scaffold(

appBar: AppBar(

title: Text(“主页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

///输出Navigator

debugPrint(navigatorKey.currentWidget.runtimeType.toString());

navigatorKey.currentState.push(MaterialPageRoute(builder: (_){

return new SecondRoute();

}));

},

child: Text(“进入第二页”),

)

],

),

),

);

}

}

class SecondRoute extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: Text(“第二页”),

),

body: Column(

children: [

Text(“第一个页面”),

RaisedButton(

onPressed: () {

//路由pop弹出

Navigator.pop(context);

},

child: Text(“返回”),

)

],

),

);

}

}

​ 在创建Navigator的时候,会给一个key,这个key可以看成一个Widget的id。这里的**_navigator就是我们指定的navigatorKey**(如果我们没指定,会给默认值的,所以不要疑惑不指定是不是就不创建Navigator了)。而通过这个key,就能够获得这个Navigator。直接获得了路由自然不需要再去查找了!

完善第一个页面


​ 之前我们编写了第一个页面显示了banner与文章列表,一般的,在点击banner与文章条目时需要进入新界面显示文章详情,而wanandroid的文章详情是一个web页面,因此我们需要增加一个新界面用于展示web

import ‘package:flutter/material.dart’;

import ‘package:flutter_webview_plugin/flutter_webview_plugin.dart’;

class WebViewPage extends StatefulWidget {

final data;

WebViewPage(this.data);

@override

_WebViewPageState createState() => _WebViewPageState();

}

class _WebViewPageState extends State {

bool isLoad = true;

FlutterWebviewPlugin flutterWebViewPlugin;

@override

void initState() {

super.initState();

flutterWebViewPlugin = new FlutterWebviewPlugin();

flutterWebViewPlugin.onStateChanged.listen((state) {

if (state.type == WebViewState.finishLoad) {

// 加载完成

setState(() {

isLoad = false;

});

} else if (state.type == WebViewState.startLoad) {

setState(() {

isLoad = true;

});

}

});

}

@override

void dispose() {

flutterWebViewPlugin.dispose();

super.dispose();

}

@override

Widget build(BuildContext context) {

///WebView插件

return WebviewScaffold(

appBar: AppBar(

title: Text(widget.data[‘title’]),

///appbar下边摆放一个进度条

bottom: PreferredSize(

preferredSize: const Size.fromHeight(1.0),

child: const LinearProgressIndicator()),

///透明度

bottomOpacity: isLoad ? 1.0 : 0.0,

),

withLocalStorage: true, //缓存,数据存储

url: widget.data[‘url’],

withJavascript: true);

}

}

flutter_webview_plugin是一个插件,需要引入:flutter_webview_plugin: ^0.3.0+2

首先我们加入banner的点击事件,在page_article.dart中修改_bannerView方法:

Widget _bannerView() {

var list = banners.map((item) {

///自动增加点击水波纹的widget

return InkWell(

child: Image.network(item[‘imagePath’], fit: BoxFit.cover), //fit 图片充满容器

///点击事件

onTap: () {

///跳转页面

Navigator.of(context).push(new MaterialPageRoute(builder: (context) {

return WebViewPage(item);

}));

},

);

最后

文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析

资料展示:

image

image

image

image

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

击水波纹的widget

return InkWell(

child: Image.network(item[‘imagePath’], fit: BoxFit.cover), //fit 图片充满容器

///点击事件

onTap: () {

///跳转页面

Navigator.of(context).push(new MaterialPageRoute(builder: (context) {

return WebViewPage(item);

}));

},

);

最后

文章所有资料全部已经打包整理好,另外小编手头上整理了大量Android架构师全套学习资料,Android核心高级技术PDF文档+全套高级学习资料+视频+2021 BAT 大厂面试真题解析

资料展示:

[外链图片转存中…(img-IiG9yda1-1714226867410)]

[外链图片转存中…(img-ePEUbgey-1714226867411)]

[外链图片转存中…(img-U4xMnDyx-1714226867411)]

[外链图片转存中…(img-kcjsVYZr-1714226867411)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值