Flutter路由和導航

xulj發表於2020-07-06

管理多個頁面時有兩個核心概念和類:Route 和 Navigator。 一個Route是一個螢幕或頁面的抽象,Navigator是管理Route的Widget。Navigator可以通過route入棧和出棧來實現頁面之間的跳轉。

1、Route

Route 一個頁面要想被路由統一管理,必須包裝為一個Route。 Route是一個抽象類,進入Route類,點選cmd+opt+B檢視其實現類。

imag01.png

/**
 * 使用 MaterialPageRoute
 * Android: 從螢幕底部滑動到頂部
 * iOS:     從螢幕右側滑動到左側
 */
Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
  return FirstPage("a home message---first");
}));

/**
 * 使用PageRouteBuilder漸變效果
 */
Navigator.of(context).push(PageRouteBuilder(pageBuilder: (ctx, anim1, anim2) {
  return FadeTransition(
      opacity: anim1, child: FirstPage("a home message----first"));
}));
                     
複製程式碼

2、Navigator

Navigator:管理所有的Route的Widget,通過一個Stack來進行管理的。

// 路由跳轉:傳入一個路由物件
Future<T> push<T extendsObject>(Route<T> route)

// 路由跳轉:傳入一個名稱(命名路由)
Future<T> pushNamed<T extendsObject>(
  String routeName, {
    Object arguments,
  })

// 路由返回:可以傳入一個引數
bool pop<T extendsObject>([ T result ])
複製程式碼
  • 實現從一個頁面跳轉到FirstPage頁面並實現相互傳值。
Future result=Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
  return FirstPage("first params");
}));

result.then((value){
  print("pop 返回---$value");
});
複製程式碼
import 'package:flutter/material.dart';

class FirstPage extends StatelessWidget {
 static const routeName="/firstPage";
 final String _message;

  FirstPage(this._message);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("first page"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_message, style: TextStyle(fontSize: 20),),
            RaisedButton(
              child: Text("first pop"),
              onPressed: () {
                Navigator.of(context).pop("first pop");
              },
            ),
          ],
        ),
      ),
    );
  }
}

複製程式碼
  • 通過命名路由實現跳轉到SecondPage,先要在入口配置路由。
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter widget',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
       //命名路由
        SecondPage.routeName:(context)=>SecondPage(),
        ThirdPage.routeName: (context) => ThirdPage(),
      },
      //由於FirstPage已經建立了構造器
      onGenerateRoute: (settings){
        if (settings.name == FirstPage.routeName) {
          return MaterialPageRoute(
              builder: (context) {
                return FirstPage(settings.arguments);
              }
          );
        }
        return null;
      },
      //未知路由
      onUnknownRoute: (settings){
        return MaterialPageRoute(
          builder: (context){
            return UnKnownPage();
          }
        );
      },
      home: MyHomePage(),
    );
  }
}
複製程式碼
Navigator.of(context).pushNamed(SecondPage.routeName, arguments: "a home message-03");
複製程式碼

SecondPage程式碼,裡面獲取引數

import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {
  static const routeName="/secondPage";

  @override
  Widget build(BuildContext context) {
    final _message = ModalRoute.of(context).settings.arguments as String;
    return Scaffold(
      appBar: AppBar(
        title: Text("second page"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_message, style: TextStyle(fontSize: 20),),
            RaisedButton(
              child: Text("second pop"),
              onPressed: () {
                Navigator.of(context).pop("second pop");
              },
            ),
          ],
        ),
      ),
    );
  }
}

複製程式碼
  • 監聽頁面的返回按鈕的兩種方式
appBar: AppBar(
  title: Text("third page"),
  leading: IconButton(
    icon: Icon(Icons.arrow_back_ios),
    onPressed: () {
      Navigator.of(context).pop("third page back");
    },
  ),
),
複製程式碼
import 'package:flutter/material.dart';

class ThirdPage extends StatelessWidget {
  static const routeName = "/thirdPage";

  @override
  Widget build(BuildContext context) {
    final _message = ModalRoute.of(context).settings.arguments as String;
    return WillPopScope(
      onWillPop: () {
        // 當返回為true時,flutter自動幫助我們執行返回操作
        // 當返回為false時, 自行寫返回程式碼
        Navigator.of(context).pop("third page back");
        return Future.value(false);
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text("third page"),
//          leading: IconButton(
//            icon: Icon(Icons.arrow_back_ios),
//            onPressed: () {
//              Navigator.of(context).pop("third pop");
//            },
//          ),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                _message,
                style: TextStyle(fontSize: 20),
              ),
              RaisedButton(
                child: Text("third pop"),
                onPressed: () {
                  Navigator.of(context).pop("third page back");
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

複製程式碼

相關文章