日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

詳解flutter如何實現局部導航管理_Android

作者:李小轟_Rex ? 更新時間: 2023-02-26 編程語言

引言

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

局部導航是什么?

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

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

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

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

實現步驟

第一步

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

///工具類:用于局部導航管理
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 示例,實現一個單獨堆棧管理的彈窗內部,對彈窗方法進行封裝處理。

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

那么子頁面內的堆棧操作(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 的回調數據
                      if (data != null) {
                        Fluttertoast.showToast(msg: 'mainPage 接收數據:$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 的回調數據
          Fluttertoast.showToast(msg: 'pageA 接收數據:$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('跳轉頁面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的數據');
              },
              child: const Text('返回pageA'),
            ),
            const SizedBox(height: 20),
            TextButton(
              onPressed: () {
                Navigator.of(context, rootNavigator: true).pop('我是來自pageC的數據');
              },
              child: const Text('關閉整個彈窗'),
            ),
          ],
        ),
      ),
    );
  }
}

技術點分析:

1. 局部 Navigator 管理重點

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

2. 返回上一級頁面,與關閉整個彈窗怎么區分?

關鍵點在于 Navigator.of(context) 中的 rootNavigator 可選入參,默認是不使用根節點下的 navigator。

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

3. 如何接收頁面關閉時回傳的數據?

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

原文鏈接:https://juejin.cn/post/7168662360230461454

欄目分類
最近更新