在這篇文章中,將帶着你們一塊兒認識什麼是Flutter的路由與導航
,如何完成不一樣頁面跳轉?
,如何獲取路由跳轉的返回記過?
,以及如何跳轉到其餘APP?
react
首頁咱們來學習在Flutter中如何實現不一樣頁面跳轉(導航)?android
Android:bash
要在Flutter中切換屏幕,咱們能夠訪問路由以繪製新的Widget。 管理多個屏幕有兩個核心概念和類:Route 和 Navigator。Route是應用程序的「屏幕」或「頁面」的抽象(能夠認爲是Activity), Navigator是管理Route的Widget。Navigator能夠經過push和poproute以實現頁面切換。app
和Android類似,咱們能夠在AndroidManifest.xml中聲明Activities,在Flutter中,咱們能夠將具備指定Route的Map傳遞到頂層MaterialApp實例,但這不是必須的。異步
iOS:async
在 iOS 中,可使用管理了 view controller 棧的 UINavigationController 來在不一樣的 view controller 之間跳轉。ide
React Native:佈局
在React Native中,可使用react-navigation來實現頁面之間的導航。學習
Flutter 也有相似的實現,使用了 Navigator和 Routes。一個路由是 App 中「屏幕」或「頁面」的抽象,而一個 Navigator是管理多個路由的 widget 。你能夠粗略地把一個路由對應到一個 UIViewController。Navigator的工做原理和 iOS 中 UINavigationController 很是類似,當你想跳轉到新頁面或者重新頁面返回時,它能夠 push() 和 pop() 路由。
在Flutter中,有兩個主要的widget用於在頁面之間導航:
以上兩種widget對應Flutter中實現頁面導航的有兩種選擇:
下面是構建一個 Map 的例子:
void main() {
runApp(MaterialApp(
home: MyAppHome(), // becomes the route named '/'
routes: <String, WidgetBuilder> {
'/a': (BuildContext context) => MyPage(title: 'page A'),
'/b': (BuildContext context) => MyPage(title: 'page B'),
'/c': (BuildContext context) => MyPage(title: 'page C'),
},
));
}
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
經過把路由的名字 push
給一個 Navigator
來跳轉:
Navigator.of(context).pushNamed('/b');
複製代碼
您還可使用Navigator
的push
方法,該方法將給定route
添加到導航器的歷史記錄中。 在如下示例中,MaterialPageRoute widget是一種模版路由,它根據平臺自適應替換整個頁面。 在如下示例中,widget是一種模版路由,它使用平臺自適應替換整個頁面。它須要一個WidgetBuilder做爲必需參數。
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context)
=> UsualNavscreen()));
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
在Android中有startActivityForResult
來獲取跳轉頁面後返回的結果,那麼在Flutter中Navigator
類不只用來處理 Flutter中的路由,還被用來獲取你剛 push
到棧中的路由返回的結果。經過 await
等待路由返回的結果來達到這點。
舉個例子,要跳轉到「位置」路由來讓用戶選擇一個地點,你可能要這麼作:
Map coordinates = await Navigator.of(context).pushNamed('/location');
複製代碼
以後,在 location 路由中,一旦用戶選擇了地點,攜帶結果一塊兒 pop() 出棧:
Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
Flutter能夠經過直接與Android層通訊並請求共享的數據來處理來自Android的Intents
在這個例子中,咱們註冊文本共享Intent
,因此其餘應用程序能夠共享文本到咱們的Flutter應用程序
這個應用程序的基本流程是咱們首先處理Android端的共享文本數據,而後等待Flutter請求數據,而後經過MethodChannel
發送。
若是你對MethodChannel還不熟悉的話能夠經過第8章 Flutter進階提高:Flutter混合開發教程進行詳細的學習
首先在在AndroidManifest.xml
中註冊咱們想要處理的Intent
:
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- ... -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
而後,在MainActivity中,您能夠處理intent,一旦咱們從intent中得到共享文本數據,咱們就會持有它,直到Flutter在完成準備就緒時請求它。
...
public class MainActivity extends FlutterActivity {
private String sharedText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}
new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.contentEquals("getSharedText")) {
result.success(sharedText);
sharedText = null;
}
}
});
}
void handleSendText(Intent intent) {
sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
}
}
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
最後,在Flutter中,您能夠在渲染Flutter視圖時請求數據。
...
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
static const platform = const MethodChannel('app.channel.shared.data');
String dataShared = "No data";
@override
void initState() {
super.initState();
getSharedText();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text(dataShared)));
}
getSharedText() async {
var sharedData = await platform.invokeMethod("getSharedText");
if (sharedData != null) {
setState(() {
dataShared = sharedData;
});
}
}
}
複製代碼
以上代碼片斷的完整部分能夠在課程源碼中查找。
在 iOS 中,要跳轉到其餘 App,你須要一個特定的 URL Scheme。對系統級別的 App 來講,這個 scheme 取決於 App。爲了在 Flutter 中實現這個功能,你能夠建立一個原平生臺的整合層,或者使用現有的 plugin,例如 url_launcher。
你們能夠經過《路由、Navigator與頁面導航開發指南》來學習Flutter頁面導航與路由的更多技巧和實戰經驗。