Flutter Navigator2.0
Example 1
import 'package:dart_printf/dart_printf.dart';
import 'package:flutter/material.dart';
class Book {
final String title;
final String author;
Book(this.title, this.author);
}
List<Book> books = [
Book('Stranger in a Strange Land', 'Robert A. Heinlein'),
Book('Foundation', 'Isaac Asimov'),
Book('Fahrenheit 451', 'Ray Bradbury'),
];
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Book _selectedBook;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Navigator(
pages: [
MaterialPage(
child: BooksPage(books: books, onTapped: _handleBookTapped),
),
if (_selectedBook != null) BookDetailsPage(book: _selectedBook)
],
onPopPage: (route, result) {
printf("page result: %o", result);
if (!route.didPop(result)) {
return false;
}
// 通过将_selectedBook设置为null来更新页面列表
setState(() {
_selectedBook = null;
});
return true;
},
),
);
}
void _handleBookTapped(Book book) {
setState(() {
_selectedBook = book;
});
}
}
class BookDetailsPage extends Page {
final Book book;
BookDetailsPage({
this.book,
}) : super(key: ValueKey(book));
Route createRoute(BuildContext context) {
return MaterialPageRoute(
settings: this,
builder: (BuildContext context) {
return BookPage(book: book);
},
);
}
}
class BooksPage extends StatelessWidget {
final List<Book> books;
final ValueChanged<Book> onTapped;
BooksPage({
@required this.books,
@required this.onTapped,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('books')),
body: ListView(
children: [
for (var book in books)
ListTile(
title: Text(book.title),
subtitle: Text(book.author),
onTap: () => onTapped(book),
)
],
),
);
}
}
class BookPage extends StatelessWidget {
final Book book;
BookPage({@required this.book});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(book.title)),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
children: [
Text(book.author),
RaisedButton(
onPressed: () => Navigator.of(context).pop(book.title),
child: Text('Pop'),
),
],
),
),
),
);
}
}
Example 2
import 'package:dart_printf/dart_printf.dart';
import 'package:flutter/material.dart';
class Book {
final String title;
final String author;
Book(this.title, this.author);
}
List<Book> books = [
Book('Stranger in a Strange Land', 'Robert A. Heinlein'),
Book('Foundation', 'Isaac Asimov'),
Book('Fahrenheit 451', 'Ray Bradbury'),
];
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
BookRouterDelegate _routerDelegate = BookRouterDelegate();
BookRouteInformationParser _routeInformationParser =
BookRouteInformationParser();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: _routerDelegate,
routeInformationParser: _routeInformationParser,
);
}
}
class BookRouteInformationParser extends RouteInformationParser<BookRoutePath> {
/// 通常在web程序中手动更改url是会收到通知
@override
Future<BookRoutePath> parseRouteInformation(RouteInformation routeInformation) async {
printf('localtion: %s', routeInformation.location);
final uri = Uri.parse(routeInformation.location);
// Handle '/'
if (uri.pathSegments.length == 0) {
return BookRoutePath.home();
}
// Handle '/book/:id'
if (uri.pathSegments.length == 2) {
if (uri.pathSegments[0] != 'book') return BookRoutePath.unknown();
var remaining = uri.pathSegments[1];
var id = int.tryParse(remaining);
if (id == null) return BookRoutePath.unknown();
return BookRoutePath.details(id);
}
// Handle unknown routes
return BookRoutePath.unknown();
}
@override
RouteInformation restoreRouteInformation(BookRoutePath path) {
if (path.isUnknown) {
return RouteInformation(location: '/404');
}
if (path.isHomePage) {
return RouteInformation(location: '/');
}
if (path.isDetailsPage) {
return RouteInformation(location: '/book/${path.id}');
}
return null;
}
}
class BookRouterDelegate extends RouterDelegate<BookRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath> {
final GlobalKey<NavigatorState> navigatorKey;
Book _selectedBook;
bool show404 = false;
BookRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();
BookRoutePath get currentConfiguration {
if (show404) {
return BookRoutePath.unknown();
}
return _selectedBook == null
? BookRoutePath.home()
: BookRoutePath.details(books.indexOf(_selectedBook));
}
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
key: ValueKey('BooksListPage'),
child: BooksPage(books: books, onTapped: _handleBookTapped),
),
if (show404)
MaterialPage(key: ValueKey('UnknownPage'), child: UnknownScreen())
else if (_selectedBook != null)
BookDetailsPage(book: _selectedBook)
],
onPopPage: (route, result) {
printf("[page result] %o", result);
if (!route.didPop(result)) {
return false;
}
// 通过将_selectedBook设置为null来更新页面列表
_selectedBook = null;
show404 = false;
notifyListeners();
return true;
},
);
}
@override
Future<void> setNewRoutePath(BookRoutePath path) async {
printf('path id: %o', path.id);
if (path.isUnknown) {
_selectedBook = null;
show404 = true;
return;
}
if (path.isDetailsPage) {
if (path.id < 0 || path.id > books.length - 1) {
show404 = true;
return;
}
_selectedBook = books[path.id];
} else {
_selectedBook = null;
}
show404 = false;
}
void _handleBookTapped(Book book) {
_selectedBook = book;
notifyListeners();
}
}
class BookDetailsPage extends Page {
final Book book;
BookDetailsPage({
this.book,
}) : super(key: ValueKey(book));
Route createRoute(BuildContext context) {
return MaterialPageRoute(
settings: this,
builder: (BuildContext context) {
return BookPage(book: book);
},
);
}
}
class BookRoutePath {
final int id;
final bool isUnknown;
BookRoutePath.home()
: id = null,
isUnknown = false;
BookRoutePath.details(this.id) : isUnknown = false;
BookRoutePath.unknown()
: id = null,
isUnknown = true;
bool get isHomePage => id == null;
bool get isDetailsPage => id != null;
}
class BooksPage extends StatelessWidget {
final List<Book> books;
final ValueChanged<Book> onTapped;
BooksPage({
@required this.books,
@required this.onTapped,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('books')),
body: ListView(
children: [
for (var book in books)
ListTile(
title: Text(book.title),
subtitle: Text(book.author),
onTap: () => onTapped(book),
)
],
),
);
}
}
class BookPage extends StatelessWidget {
final Book book;
BookPage({@required this.book});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(book.title)),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
children: [
Text(book.author),
RaisedButton(
onPressed: () => Navigator.of(context).pop(book.title),
child: Text('Pop'),
),
],
),
),
),
);
}
}
class UnknownScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('404')),
body: Center(
child: Text('404!'),
),
);
}
}
See also:
Flutter Navigator2.0的更多相关文章
- Flutter 1.0 正式版: Google 的便携 UI 工具包
Flutter 1.0 正式版: Google 的便携 UI 工具包 文 / Tim Sneath,Google Dart & Flutter 产品组产品经理 Flutter 是 Google ...
- Flutter 1.0 正式版: Google 的便携 UI 工具包
简评:所以 React-Native 和 Flutter 该怎么选? 在 10 个月前的 MWC 上,谷歌发布了 Flutter 的 Beta 版本,给跨平台应用开发带来了一种全新的选择,昨天谷歌正式 ...
- Flutter 1.0 正式版: Google 的跨平台 UI 工具包
今天我们非常高兴的宣布,Flutter 的 1.0 版本正式发布!Flutter 是 Google 为您打造的 UI 工具包,帮助您通过一套代码同时在 iOS 和 Android 上构建媲美原生体验的 ...
- 【老孟Flutter】Flutter 2.0 重磅更新
老孟导读:昨天期待已久的 Flutter 2.0 终于发布了,Web 端终于提正了,春季期间我发布的一篇文章,其中的一个预测就是 Web 正式发布,已经实现了,还有一个预测是:2021年将是 Flut ...
- XD to Flutter 2.0 现已发布!
Flutter 是 Google 的开源 UI 工具包.利用它,只需一套代码库,就能开发出适合移动设备.桌面设备.嵌入式设备以及 web 等多个平台的精美应用.过去几年,对于想要打造多平台应用的开发者 ...
- 写在Flutter 1.0之前
开始 大概有半年没有写东西了,感觉时间过得飞快,18年也过一小半,趁着谷歌大会再为Flutter这个耀眼的新星,再吹一波! 都beta3了,1.0还会远吗 Flutter团队依然不紧不慢,一步一个脚印 ...
- 学习Flutter从0开始
一. 认识Flutter 1.1. 什么是Flutter 先看看官方的解释: Flutter is Google's UI toolkit for building beautiful, native ...
- 颤振错误:当前Flutter SDK版本为2.1.0-dev.0.0.flutter-be6309690f?
我刚刚升级了我的扑动,升级后我无法在Android Studio上运行任何扑动项目.我收到此错误消息. The current Dart SDK version -dev.0.0.flutter-be ...
- 编写第一个Flutter App(翻译)
博客搬迁至http://blog.wangjiegulu.com RSS订阅:http://blog.wangjiegulu.com/feed.xml 以下代码 Github 地址:https://g ...
随机推荐
- assets和static的区别
相同点:assets和static两个都是存放静态资源文件.项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点不相同点:assets中存放的静态资源文件在项目打包时,也 ...
- 手把手教你定位常见Java性能问题
概述 性能优化一向是后端服务优化的重点,但是线上性能故障问题不是经常出现,或者受限于业务产品,根本就没办法出现性能问题,包括笔者自己遇到的性能问题也不多,所以为了提前储备知识,当出现问题的时候不会手忙 ...
- Spring常见问题总结
1. 什么是 Spring 框架? Spring 是一种轻量级开发框架,旨在提高开发人员的开发效率以及系统的可维护性.Spring 官网:https://spring.io/. 我们一般说 Sprin ...
- python模块----sys模块 (系统相关的参数和函数)
pprint 模块:它给我们提供了一个方法 pprint() 该方法可以用来对打印的数据做简单的格式化 sys模块+pprint模块 标准库网址(sys):https://docs.python.or ...
- Linux-yum安装和相关命令
Linux-yum安装和相关命令 一 yum yum命令是在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包,能够从指定的服务 ...
- F - Cheapest Palindrome
有一个长度为m的字符串,由n种小写字母组成.对应的n种字母在这个字符串加上或者减去都有相应的费用,现在要将这个字符串变成回文串,问最低消费是多少? Keeping track of all the c ...
- 【uva 11491】Erasing and Winning(算法效率--贪心+单调队列)
题意:有一个N位整数,要求输出删除其中D个数字之后的最大整数. 解法:贪心.(P.S.要小心,我WA了2次...)由于规定了整数的位数,那么我们要尽量让高位的数字大一些,也就是要尽量删去前面小的数字. ...
- poj 3304 Segments(解题报告)
收获:举一反三:刷一道会一道 1:思路转化:(看的kuangbin的思路) 首先是在二维平面中:如果有很多线段能够映射到这个直线上并且至少重合于一点,充要条件: 是过这个点的此条直线的垂线与其他所有直 ...
- Codeforces Round #579 (Div. 3) E. Boxers (贪心)
题意:给你一组数,每个数都可以进行一次加一减一,问最后最多能有多少不同的数. 题解:我们可以用桶存每个数的次数,然后枚举\([1,150001]\)来求对答案的贡献,然后贪心,这里我们不用担心其他乱七 ...
- BKDR字符串哈希
BKDR字符串哈希 bkdrhash冲突的可能性非常小,但是由于\(hash\)值非常大不能映射到哈希数组地址上,所以可以通过取余,用余数作为索引地址.但这样做造成了可能的地址冲突. #include ...