欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解flutter如何實現(xiàn)局部導航管理

 更新時間:2023年01月11日 10:02:58   作者:李小轟_Rex  
這篇文章主要為大家介紹了詳解flutter如何實現(xiàn)局部導航管理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

今天,小編給大家分享如何在 flutter 中實現(xiàn) ‘局部導航’。開始之前我們先來統(tǒng)一一下關(guān)于 局部導航 的概念。

局部導航是什么?

我們在 flutter 中使用 navigator 來管理 app 的頁面堆棧,主要包括 push、pop 這兩種操作。而當我們UI設(shè)計劃分得更細致時,可能遇到需要在某個獨立頁面里,單獨維護一套子級的堆棧管理。這就叫 局部導航管理

局部控件內(nèi)單獨維護局部范圍內(nèi)的堆棧管理的形式有很多,例如:

  • 形式一: 左側(cè)是菜單欄,右側(cè)是內(nèi)容塊,在內(nèi)容塊中單獨維護局部的頁面push、pop、操作。
  • 形式二:dialog 彈窗中單獨維護布局堆棧管理。

那么下面,小編使用 dialog 的形式來分享實現(xiàn)過程。

實現(xiàn)步驟

第一步

創(chuàng)建工具類,用于局部導航管理,思想是:將需要單獨進行堆棧管理的頁面使用新的子級 navigator 進行包裹,單獨維護一個 navigator,做到每個堆棧容器實現(xiàn)內(nèi)部各自管理。

///工具類:用于局部導航管理
class LocalNavigator extends StatelessWidget {
  final Widget child;
  const LocalNavigator(this.child, {Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Navigator(
      initialRoute: '/',
      onGenerateRoute: (settings) {
        return MaterialPageRoute(
          settings: const RouteSettings(name: '/'),
          builder: (context) {
            return child;
          },
        );
      },
    );
  }
}

第二步

如上 demo 示例,實現(xiàn)一個單獨堆棧管理的彈窗內(nèi)部,對彈窗方法進行封裝處理。

showDialog 時使用我們封裝的工具類 LocalNavigator 作為父節(jié)點,對具體子頁面節(jié)點進行包裹。

那么子頁面內(nèi)的堆棧操作(push 、pop、)都會在我們的 LocalNavigator 堆棧中響應。

/// 通過局部導航開啟一個彈窗
  static Future<T?> showLocalDialog<T>(
    BuildContext context,
    Widget child,
  ) {
    return showDialog<T?>(
      context: context,
      builder: (context) {
        return Dialog(
          child: SizedBox(
            width: 200,
            height: 300,
            child: LocalNavigator(child),
          ),
        );
      },
    );
  }

第三步

彈出 dialog,附上 demo 樣例的完整代碼

void main() {
  runApp(const Material(
    child: MyApp(),
  ));
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('demo'),
        ),
        body: StatefulBuilder(
          builder: (context, setState) {
            return Center(
              child: TextButton(
                child: const Text('打開彈窗'),
                onPressed: () {
                 showLocalDialog<String?>(context, const _PageA())
                      .then(
                    (data) {
                      //接收來自 dialog 的回調(diào)數(shù)據(jù)
                      if (data != null) {
                        Fluttertoast.showToast(msg: 'mainPage 接收數(shù)據(jù):$data');
                      }
                    },
                  );
                },
              ),
            );
          },
        ),
      ),
    );
  }
}
class _PageA extends StatelessWidget {
  const _PageA({Key? key}) : super(key: key);
  void jumpPageB(BuildContext context) {
    Navigator.push<String?>(
      context,
      MaterialPageRoute(
        builder: (context) => const _PageB(),
      ),
    ).then(
      (data) {
        if (data != null) {
          //接收來自 pageB 的回調(diào)數(shù)據(jù)
          Fluttertoast.showToast(msg: 'pageA 接收數(shù)據(jù):$data');
        }
      },
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('PageA')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () {
                jumpPageB(context);
              },
              child: const Text('跳轉(zhuǎn)頁面B'),
            ),
          ],
        ),
      ),
    );
  }
}
class _PageB extends StatelessWidget {
  const _PageB({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('PageB')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop('我是來自pageB的數(shù)據(jù)');
              },
              child: const Text('返回pageA'),
            ),
            const SizedBox(height: 20),
            TextButton(
              onPressed: () {
                Navigator.of(context, rootNavigator: true).pop('我是來自pageC的數(shù)據(jù)');
              },
              child: const Text('關(guān)閉整個彈窗'),
            ),
          ],
        ),
      ),
    );
  }
}

技術(shù)點分析:

1. 局部 Navigator 管理重點

將 需要維護局部堆棧關(guān)系的子節(jié)點 進行嵌套,使用自定義的工具類 LocalNavigator 作為父節(jié)點。

2. 返回上一級頁面,與關(guān)閉整個彈窗怎么區(qū)分?

關(guān)鍵點在于 Navigator.of(context) 中的 rootNavigator 可選入?yún)?,默認是不使用根節(jié)點下的 navigator。

  • 返回上一級頁面,使用當前的堆棧進行操作 Navigator.of(context).pop()
  • 關(guān)閉整個彈窗,意味著在根堆棧進行 pop 操作 Navigator.of(context, rootNavigator: true).pop()

3. 如何接收頁面關(guān)閉時回傳的數(shù)據(jù)?

  • 關(guān)閉時通過 pop() 方法進行數(shù)據(jù)回傳 Navigator.of(context).pop(data)
  • 接收回傳數(shù)據(jù),在打開新堆棧的 push 方法中接收回返回值 Navigator.push<T?>(context, route).then((T){ }) T 為返回值的泛型標識,注意在接收處理的地方需要對返回值進行判空操作
Navigator.push<String?>(
      context,
      MaterialPageRoute(
        builder: (context) => const _PageB(),
      ),
    ).then(
      (data) {
        if (data != null) {
          //接收來自 pageB 的回調(diào)數(shù)據(jù)
          Fluttertoast.showToast(msg: 'pageA 接收數(shù)據(jù):$data');
        }
      },
    );

以上就是詳解flutter如何實現(xiàn)局部導航管理的詳細內(nèi)容,更多關(guān)于flutter局部導航管理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論