在 Flutter 中想要實現頁面間的跳轉和傳值的話,離不開兩種路由:git
官方說的是靜態路由和動態路由,不過我習慣了這樣叫,因此就暫且這樣說吧!bash
基本路由的跳轉
使用push
跳到指定的頁面,而後再使用pop
回到原來的頁面app
不過當你跳轉過去的時候,人家默認會有一個返回的箭頭按鈕,點擊就能夠返回less
開始擼代碼異步
我在main.dart
文件中引用了Home.dart
文件
在Home.dart
文件中有一個按鈕,當我點擊的時候,能夠跳到詳情頁面async
注:若是用stl
生成的靜態控件是不能用跳轉按鈕的ide
Home.dart
文件代碼:測試
//Home.dart
import 'package:flutter/material.dart';
import './Detail.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
RaisedButton(
child: Text('跳到詳情頁面'),
onPressed: (){
//跳轉頁面
Navigator.of(context).push(
MaterialPageRoute(
//沒有傳值
builder: (context)=>Detail()
)
);
},
)
],
),
);
}
}
複製代碼
當我點擊了按鈕的時候,就能夠跳到詳情頁面:
Detail.dart
文件代碼:優化
import 'package:flutter/material.dart';
class Detail extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//浮動按鈕
floatingActionButton: FloatingActionButton(
child: Text('返回'),
onPressed: (){
Navigator.of(context).pop();
},
),
appBar: AppBar(title: Text("詳情頁面"),),
body: Text("詳情頁面"),
);
}
}
複製代碼
如圖,跳過去後默認會有一個返回按鈕,點擊後就能夠返回 ,
也能夠本身定義一個按鈕,利用pop
方法點擊後也能夠返回ui
有時候咱們跳轉的時候須要傳遞參數,
這時候咱們就要攜帶參數跳轉,固然很是簡單
咱們須要在使用參數的頁面定義一個變量,注意須要設置默認值,若是沒給你傳值的時候使用默認值
而後在跳轉的時候給目標頁面傳值
Home.dart
文件代碼:
//Home.dart
//只貼按鈕的代碼,其他的和上面同樣
RaisedButton(
child: Text('跳到詳情頁面'),
onPressed: (){
//跳轉頁面
Navigator.of(context).push(
MaterialPageRoute(
//傳值
builder: (context)=>Detail(Test:'我是參數')
//沒傳值
//builder: (context)=>Detail()
)
);
},
)
複製代碼
而後在目標頁面接收,若是沒傳值默認爲上面定義的默認值
Detail.dart
文件代碼:
class Detail extends StatelessWidget {
//須要定義變量和默認值
String Test;
Detail({this.Test='沒有給我傳值'});
@override
Widget build(BuildContext context) {
return Scaffold(
//浮動按鈕
floatingActionButton: FloatingActionButton(
child: Text('返回'),
onPressed: (){
Navigator.of(context).pop();
},
),
appBar: AppBar(title: Text("詳情頁面"),),
body: Text(this.Test),
);
}
}
複製代碼
有時候咱們跳轉的時候不須要傳值,而當你返回的時候須要從子組件中接收值
用下面這個例子來講明:
新建兩個dart文件AddressList.dart
和GetAddress.dart
文件,在mian.dart
中使用GetAddress.dart
文件
咱們想要點擊GetAddress.dart
文件中的 選擇收穫地址 按鈕,跳到添加地址頁面,而後選擇地址後,直接帶着數據返回到首頁面並顯示出來
代碼示例:
main.dart
文件只改了須要渲染的控件
import 'package:flutter/material.dart';
import './address/GetAddress.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Route"),
),
body: GetAddress()
),
);
}
}
複製代碼
注意獲取數據都是異步的,須要加async、await
改變數據的惟一方式是利用setState
方法
GetAddress.dart
文件代碼:
import 'package:flutter/material.dart';
import './AddressList.dart';
class GetAddress extends StatefulWidget {
@override
_GetAddressState createState() => _GetAddressState();
}
class _GetAddressState extends State<GetAddress> {
//定義一個變量
String _ads = '';
@override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
appBar: AppBar(title: Text('獲取收穫地址'),),
body: Center(
child: Column(
//垂直居中
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
//按鈕主題
textTheme: ButtonTextTheme.primary,
color: Theme.of(context).accentColor,
child: Text('選擇收貨地址'),
//點擊
onPressed: () async {
//經過路由跳轉從子頁面中傳遞過來的數據,都是異步的
var ads = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context){
return AddressList();
}
)
);
setState(() {
_ads = ads;
});
},
),
Text('${_ads==""?"未查到收貨地址":_ads}')
],
),
),
),
);
}
}
複製代碼
利用onTap
點擊後直接使用pop
返回到首頁面,並把數據帶回去
AddressList.dart
文件代碼:
import 'package:flutter/material.dart';
class AddressList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("個人地址列表"),),
body: ListView(
padding: EdgeInsets.all(10),
children: <Widget>[
GestureDetector(
onTap: (){
//pop後面能夠跟上參數
Navigator.of(context).pop('北京');
},
//給子組件添加事件
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black26)
),
child: ListTile(
leading: Icon(
Icons.account_box,
color: Colors.blue,
),
title: Text(
'北京',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
),
//給控件中間加間隙
SizedBox(height: 10),
GestureDetector(
onTap: (){
//pop後面能夠跟上參數
Navigator.of(context).pop('河南');
},
//給子組件添加事件
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black26)
),
child: ListTile(
leading: Icon(
Icons.account_box,
color: Colors.blue,
),
title: Text(
'河南',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
),
//給控件中間加間隙
SizedBox(height: 10),
GestureDetector(
onTap: (){
//pop後面能夠跟上參數
Navigator.of(context).pop('上海');
},
//給子組件添加事件
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black26)
),
child: ListTile(
leading: Icon(
Icons.account_box,
color: Colors.blue,
),
title: Text(
'上海',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
)
],
),
);
}
}
複製代碼
相似於 Vue 中的路由
新建了幾個頁面Main.dart
、Page1.dart
、Page1.dart
和Page3.dart
用來測試
引入文件,
在main.dart
中的routes
中配置路徑(必須在main.dart中配置)
body
換成須要渲染的頁面
main.dart
文件代碼:
import 'package:flutter/material.dart';
import './files/Page1.dart';
import './files/Page2.dart';
import './files/Page3.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Route"),
),
body: Main(),
),
//定義路由
routes: {
//須要使用context指定上下文
'/page1': (context) => Page1(),
'/page2': (context) => Page2(),
'/page3': (context) => Page3(),
},
);
}
}
複製代碼
在Main.dart
文件中寫兩個按鈕用來跳轉(注意一個是main.dart
一個是Main.dart
)
Main.dart
文件代碼:
import 'package:flutter/material.dart';
class Main extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: <Widget>[
//定義按鈕
RaisedButton(
child: Text("跳轉到Page1"),
onPressed: () {
//須要使用pushNamed方法
Navigator.pushNamed(context, "/page1");
},
),
SizedBox(height: 20),
RaisedButton(
child: Text("跳轉到Page2"),
onPressed: () {
Navigator.pushNamed(context, "/page2");
},
),
],
),
),
),
);
}
}
複製代碼
點擊按鈕跳轉到指定頁面,Page1.dart
、Page2.dart
、Page3.dart
頁面的基本結構,只貼一個頁面看一下:
Page1.dart
文件代碼:
import 'package:flutter/material.dart';
class Page1 extends StatefulWidget {
@override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page1"),),
body: Text("Page1",style: TextStyle(fontSize: 40),),
);
}
}
複製代碼
通常咱們使用命名式路由的話,不用上面的方式,咱們都是單獨把路由抽離出去
優化上面的代碼:
新建一個Routes.dart
文件用來存放路由規則,
Routes.dart
文件代碼:
import 'package:flutter/material.dart';
//引入文件
import '../files/Main.dart';
import '../files//Page1.dart';
import '../files//Page2.dart';
import '../files//Page3.dart';
//配置路由規則
final routes = {
'/': (context) => Main(),
'/page1': (context) => Page1(),
'/page2': (context) => Page2(),
'/page3': (context) => Page3(),
};
// 若是你要把路由抽離出去,必須寫下面這一堆的代碼,不用理解什麼意思
var onGenerateRoute = (RouteSettings settings) {
// 統一處理
final String name = settings.name;
final Function pageContentBuilder = routes[name];
if (pageContentBuilder != null) {
if (settings.arguments != null) {
final Route route = MaterialPageRoute(
builder: (context) =>
pageContentBuilder(context, arguments: settings.arguments));
return route;
} else {
final Route route =
MaterialPageRoute(builder: (context) => pageContentBuilder(context));
return route;
}
}
};
複製代碼
而後在main.dart
文件中配置使用:
import 'package:flutter/material.dart';
//引入Routes.dart文件
import './routes/Routes.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/', //配置默認訪問路徑
onGenerateRoute:onGenerateRoute, //必須加上這一行,固定寫法
);
}
}
複製代碼
配置好後,別的地方都不用動,這樣就實現了咱們的路由抽離
緊跟着上面的代碼,當咱們使用命名式路由,而且把路由抽離後進行跳轉時,咱們想要跳轉過去的時候給他傳值,那麼怎麼辦呢?很簡單
在上面代碼的基礎上改動
改變Main.dart
文件中的按鈕方法,當跳轉的時候傳值,以下:
只粘貼第二個跳轉按鈕,別的代碼不用動
RaisedButton(
child: Text("跳轉到Page2"),
onPressed: () {
Navigator.pushNamed(context, "/page2",arguments: {
"id":102
});
},
),
複製代碼
而後在Routes.dart
文件中改變page2
路由規則:
'/page2': (context,{arguments}) => Page2(arguments:arguments),
複製代碼
最後在Page2.dart
頁面定義變量,重構,接收傳遞過來的值:
import 'package:flutter/material.dart';
class Page2 extends StatefulWidget {
//定義一個變量
final arguments;
//重構
Page2({this.arguments});
@override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page2"),),
//使用傳遞過來的值
body: Text("${widget.arguments['id']}",style: TextStyle(fontSize: 40),),
);
}
}
複製代碼
點擊-->源碼地址