在這篇文章中,將帶著大家一起認識什麼是Flutter的路由與導航
,如何完成不同頁面跳轉?
,如何獲取路由跳轉的返回記過?
,以及如何跳轉到其他APP?
首頁我們來學習在Flutter中如何實現不同頁面跳轉(導航)?
在Flutter中如何實現不同頁面跳轉(導航)?
Android:
要在Flutter中切換螢幕,我們可以訪問路由以繪製新的Widget。 管理多個螢幕有兩個核心概念和類:Route 和 Navigator。Route是應用程式的“螢幕”或“頁面”的抽象(可以認為是Activity), Navigator是管理Route的Widget。Navigator可以通過push和poproute以實現頁面切換。
和Android相似,我們可以在AndroidManifest.xml中宣告Activities,在Flutter中,我們可以將具有指定Route的Map傳遞到頂層MaterialApp例項,但這不是必須的。
iOS:
在 iOS 中,可以使用管理了 view controller 棧的 UINavigationController 來在不同的 view controller 之間跳轉。
React Native:
在React Native中,可以使用react-navigation來實現頁面之間的導航。
Flutter 也有類似的實現,使用了 Navigator和 Routes。一個路由是 App 中“螢幕”或“頁面”的抽象,而一個 Navigator是管理多個路由的 widget 。你可以粗略地把一個路由對應到一個 UIViewController。Navigator的工作原理和 iOS 中 UINavigationController 非常相似,當你想跳轉到新頁面或者從新頁面返回時,它可以 push() 和 pop() 路由。
在Flutter中,有兩個主要的widget用於在頁面之間導航:
- Route是一個應用程式抽象的螢幕或頁面;
- Navigator 是一個管理路由的widget;
以上兩種widget對應Flutter中實現頁面導航的有兩種選擇:
- 具體指定一個由路由名構成的 Map。(MaterialApp)
- 直接跳轉到一個路由。(WidgetApp)
下面是構建一個 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中處理來自外部應用程式傳入的Intents?(Android)
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;
});
}
}
}
複製程式碼
以上程式碼片段的完整部分可以在課程原始碼中查詢。
怎麼跳轉到其他 App?
在 iOS 中,要跳轉到其他 App,你需要一個特定的 URL Scheme。對系統級別的 App 來說,這個 scheme 取決於 App。為了在 Flutter 中實現這個功能,你可以建立一個原生平臺的整合層,或者使用現有的 plugin,例如 url_launcher。
大家可以通過《路由、Navigator與頁面導航開發指南》來學習Flutter頁面導航與路由的更多技巧和實戰經驗。
未完待續
- Flutter入門基礎知識
- Flutter主題和文書處理
- Flutter什麼是宣告式UI
- Flutter佈局與列表
- Flutter手勢檢測及觸控事件處理
- Flutter狀態管理d
- Flutter執行緒和非同步UI
- Flutter表單輸入與富文字
- Flutter認識檢視(Views)md
- Flutter呼叫硬體、第三方服務以及平臺互動、通知
- Flutter路由與導航
- Flutter專案結構、資源、依賴和本地化