本文對應github地址Flutter11,若是因爲github調整致使資源找不到,請訪問githubgit
路由
簡介github
靜態路由pushbash
// MaterialApp初始化時配置Key-Value
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.red,
primarySwatch: Colors.blue,
),
home: DDYBottomBar(),
showPerformanceOverlay: false,
routes: {
'/home/qrcode': (BuildContext context) => QRCodeScanner(title: '0',),
'/home_qrcode': (BuildContext context) => QRCodeScanner(title: '1',),
'+home_qrcode': (BuildContext context) => QRCodeScanner(title: '2',),
},
);
}
}
// 在須要的地方調用['/home/qrcode'只是字符串名字,並非真正路徑,這樣仿路徑是爲了可讀性]
// Navigator.pushNamed(context, '/home/qrcode');
// Navigator.pushNamed(context, '/home_qrcode');
// Navigator.pushNamed(context, '+home_qrcode');
Navigator.of(context).pushNamed('+home_qrcode');
複製代碼
動態路由push閉包
// Navigator.push(context, MaterialPageRoute(builder: (context) => QRCodeScanner()));
// Navigator.of(context).push(MaterialPageRoute(builder: (_) => QRCodeScanner()));
Navigator.of(context).push(MaterialPageRoute(builder: (context) => QRCodeScanner()));
複製代碼
路由popless
// Navigator.of(context).pop();
// Navigator.pop(context);
Navigator.of(context).pop('回調數據');
複製代碼
頁面傳值異步
正向傳值直接經過簡單構造函數參數方式便可async
反向傳值,不一樣風格其實都同樣,建議第一種ide
// 風格1
pushQRCodeScannerAndCallbackData1() {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => QRCodeScanner())).then((value){
print('1 $value');
});
}
// 風格2
pushQRCodeScannerAndCallbackData2() {
Future callbackFuture = Navigator.of(context).push(MaterialPageRoute(builder: (_) => QRCodeScanner()));
callbackFuture.then((value){
print('2 $value');
});
}
// 風格3
pushQRCodeScannerAndCallbackData3() async {
// 若是知道類型
String callbackString = await Navigator.of(context).push<String>(
MaterialPageRoute(builder: (context){
// 正向傳值直接經過簡單構造函數參數方式便可
return QRCodeScanner(title:'I am 3');
})
);
if (callbackString != null) {
print('3 ${callbackString}');
}
}
// pop()函數參數值即爲反向傳回的數據
Navigator.of(context).pop('回調數據');
複製代碼
還能夠經過閉包做爲參數進行傳值函數
pushQRCodeGenerator() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => QRCodeGenerator((String value) {
print('QRCodeGenerator callback $value');
}),
),
);
}
// 調用
IconButton(
icon: Icon(Icons.print),
onPressed: () {
if (widget.callbackFunction != null) {
widget.callbackFunction('回調數據');
}
},
),
複製代碼
繼承路由子類,如:PopupRoute、ModalRoute 等ui
使用 PageRouteBuilder 類經過回調函數定義路由
pushQRCodeScannerWithCustomAnimation() {
Navigator.push(
context,
PageRouteBuilder(pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return QRCodeScanner();
}, transitionsBuilder: (context, animation, secondaryAnimation, child) {
return transitionAnimation(animation, child);
}),
);
}
static SlideTransition transitionAnimation(Animation<double> animation, Widget child) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.0, 1.0),
end: const Offset(0.0, 0.0),
).animate(animation),
child: child,
);
}
複製代碼
pushQRCodeScannerWithCustomAnimation2() async {
// 頁面旋轉淡出的效果
transitionAnimation(Animation<double> animation, Widget child) {
return FadeTransition(
opacity: animation,
child: RotationTransition(
turns: Tween<double>(begin: 0.7, end:1.0).animate(animation),
child: child,
),
);
}
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, _, __) => QRCodeScanner(),
transitionDuration: const Duration(milliseconds: 1000),
transitionsBuilder: (_, animation, __, child) => transitionAnimation(animation, child),
),
).then((value){
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text(value),
duration: const Duration(seconds: 3),
),
);
});
}
複製代碼
一個應用程序可使用多個路由導航器
可將一個導航器嵌套在另外一個導航器下方使用,例如選項卡式導航,用戶註冊,訂單與結帳頁等
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (BuildContext context) => HomePage(),
'/signup': (BuildContext context) => SignUpPage(),
},
);
}
}
class SignUpPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Navigator(
initialRoute: 'signup/personal_info',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch (settings.name) {
case 'signup/personal_info':
// 我的信息完畢後到 'signup/choose_credentials'.
builder = (BuildContext _) => CollectPersonalInfoPage();
break;
case 'signup/choose_credentials':
// 選完credentials 調用 'onSignupComplete()'.
builder = (BuildContext _) => ChooseCredentialsPage(
onSignupComplete: () {
// 回到路由根頁面 '/' (HomePage)
Navigator.of(context).pop();
},
);
break;
default:
throw Exception('Invalid route: ${settings.name}');
}
return MaterialPageRoute(builder: builder, settings: settings);
},
);
}
}
複製代碼
Navigator
pushName結合配置routes,利用命名路由形式將指定頁面實例(帶固定參數)入棧,而push則是在須要跳轉時生成要跳轉的頁面對象,傳遞想要的參數,二者運行效果沒差異。
二者都是取代棧頂元素,運行效果沒差異。
顧名思義,先pop而後push
二者都是入棧新頁面刪除除該頁面實例外其餘棧內實例,將該實例做爲新棧底,運行效果沒差異。可用在註冊登陸頁登陸後跳轉,防止能返回註冊登陸頁
判斷是否能夠pop,若是能夠返回true,不然返回false
表示在該頁面嘗試pop,若是能夠則pop到前一頁,不然仍停在該頁面,丟棄該次pop
pop回棧內(該頁面實例如下)指定頁面實例,如 Navigator.popUntil(context, ModalRoute.withName('/home'));
,回到配置名爲home的頁面。
其餘知識點
去除返回按鈕 AppBar中
automaticalImplyLeading: false
複製代碼
Popup routes (彈出路由)
路由不必定要遮擋整個屏幕。 PopupRoutes 使用 ModalRoute.barrierColor 覆蓋屏幕,ModalRoute.barrierColor 只能部分不透明以容許當前屏幕顯示。 彈出路由是「模態」的,由於它們阻止了對下面其餘組件的輸入。
有一些方法能夠建立和顯示這類彈出路由。 例如:showDialog,showMenu 和 showModalBottomSheet。 如上所述,這些函數返回其推送路由的 Future(異步數據,參考下面的數據部分)。 執行能夠等待返回的值在彈出路由時執行操做。
還有一些組件能夠建立彈出路由,如 PopupMenuButton 和 DropdownButton。 這些組件建立 PopupRoute 的內部子類,並使用 Navigator 的push 和 pop 方法來顯示和關閉它們。
參考
上一頁 Flutter10 Icon、Color、Tabbar、BottomNavigationBar
下一頁 Flutter12 ListBody、ListView、ListTile