)
],
),
);
}
}
同时我们也可以对动画进行组合
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(“返回”),
)
],
),
);
}
}
这段代码运行会出现错误:
问题关键点在于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 大厂面试真题解析
资料展示:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!