導向到一個新頁面和回傳
我們通常會用『屏』來表示應用的不同頁面(介面)。比如,某個應用有一『屏』展示商品清單,當用戶點選某個商品的圖片,會跳到新的一『屏』展示商品的詳細訊息。
在 Android 開發中,Activity 相當於『路由』,在 iOS 開發中,ViewController 相當於『路由』。在 Flutter 中,『路由』也是一個 widget。
怎麼樣從一個『路由』跳轉到新的『路由』呢?Navigator
類。
這個教程裡我們使用 Navigator
來跳轉到一個新的『路由』:
步驟
下面來展示如何在兩個路由間跳轉,總共分三步:
-
建立兩個路由
-
用 Navigator.push() 跳轉到第二個路由
-
用 Navigator.pop() 回退到第一個路由
1. 建立兩個路由
首先,我們來建立兩個路由。這是個最簡單的例子,每個路由只包含一個按鈕。點選第一個路由上的按鈕會跳轉到第二個路由,點選第二個路由上的按鈕,會回退到第一個路由。
首先來編寫介面佈局程式碼:
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
// Navigate to second route when tapped.
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// Navigate back to first route when tapped.
},
child: const Text('Go back!'),
),
),
);
}
}
2. 用 Navigator.push() 跳轉到第二個路由
使用 Navigator.push()
方法跳轉到新的路由,
push()
方法會新增一個 Route
物件到導向器的堆疊上。那麼這個 Route
物件是從哪裡來的呢?你可以自己實現一個,或者直接使用 MaterialPageRoute
類。使用 MaterialPageRoute
是非常方便的,框架已經為我們實現了和平台原生類似的切換動畫。
在 FirstRoute
widget 的 build()
方法中,我們來修改 onPressed()
回呼函式:
// Within the `FirstRoute` widget
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
}
3. 用 Navigator.pop() 回退到第一個路由
怎麼關閉第二個路由回退到第一個呢?
使用 Navigator.pop()
方法,
pop()
方法會從導向器堆疊上移除 Route
物件。
實現回傳第一個頁面,更新 SecondRoute
widget
的 onPressed()
方法回呼。
// Within the SecondRoute widget
onPressed: () {
Navigator.pop(context);
}
互動式範例
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
Navigation with CupertinoPageRoute
In the previous example you learned how to navigate between screens
using the MaterialPageRoute
from Material Components.
However, in Flutter you are not limited to Material design language,
instead, you also have access to Cupertino (iOS-style) widgets.
Implementing navigation with Cupertino widgets follows the same steps
as when using MaterialPageRoute
,
but instead you use CupertinoPageRoute
which provides an iOS-style transition animation.
In the following example, these widgets have been replaced:
-
MaterialApp
replaced byCupertinoApp
. -
Scaffold
replaced byCupertinoPageScaffold
. -
ElevatedButton
replaced byCupertinoButton
.
This way, the example follows the current iOS design language.
import 'package:flutter/cupertino.dart';
void main() {
runApp(const CupertinoApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
const FirstRoute({super.key});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('First Route'),
),
child: Center(
child: CupertinoButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('Second Route'),
),
child: Center(
child: CupertinoButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}