兩分鐘帶你快速掌握Flutter的路由與導航

爲你們傾力打造的課程《Flutter從入門到進階-實戰攜程網App》上線了,點我Get!!!html

在這篇文章中,將帶着你們一塊兒認識什麼是Flutter的路由與導航如何完成不一樣頁面跳轉?如何獲取路由跳轉的返回記過?,以及如何跳轉到其餘APP?react

首頁咱們來學習在Flutter中如何實現不一樣頁面跳轉(導航)?android

在Flutter中如何實現不一樣頁面跳轉(導航)?

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用於在頁面之間導航:

  • 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');
複製代碼

您還可使用Navigatorpush方法,該方法將給定route添加到導航器的歷史記錄中。 在如下示例中,MaterialPageRoute widget是一種模版路由,它根據平臺自適應替換整個頁面。 在如下示例中,widget是一種模版路由,它使用平臺自適應替換整個頁面。它須要一個WidgetBuilder做爲必需參數。

Navigator.push(context, MaterialPageRoute(builder: (BuildContext context)
 => UsualNavscreen()));
複製代碼

以上代碼片斷的完整部分能夠在課程源碼中查找。

如何獲取路由跳轉返回的結果?

在Android中有startActivityForResult來獲取跳轉頁面後返回的結果,那麼在FlutterNavigator類不只用來處理 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項目結構、資源、依賴和本地化

參考

相關文章
相關標籤/搜索