banner
MiniKano

MiniKano

This is MiniKano's blog based on Blockchain technology. 新手,请多关照~
github

Flutter 路由配置

flutter 路由#

** 路由 (Route)** 在 WEB 開發中單頁面應用裡很常見,Flutter 也有自己的路由,但是因為在 Android 系統中,Route 指的是一個 Activity 在 IOS 系統中指的是一個 View Controller
路由管理就是使用路由棧進行 push 和 pop 的操作,將路由推入和彈出,入棧意味著打開一個新頁面,出棧代表著關閉一個頁面;除了使用路由棧之外,還需要其他的操作,例如路由攔截,路由重定向等。。

普通路由和路由跳轉#

1. 創建一個名為 MyText 的新路由 (可以進行參數傳遞)

class MyText extends StatefulWidget {
  //其他頁面跳轉到Form頁面進行命名路由傳值
  final Map arguments;
  const MyText({super.key, required this.arguments});

  @override
  State<MyText> createState() => _MyTextState();
}

class _MyTextState extends State<MyText> {
    
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Route"),
      ),
      body: Center(
        child: Text(widget.arguments.toString()),
      ),
    );
  }
}

2. 在其他任意 widget 中使用該路由 (需要提前 import), 這裡使用 ElevatedButton 做演示,按鈕點擊後就會跳轉到新路由(順帶傳遞參數)

//imported
ElevatedButton(
    onPressed: () {
        //路由
        //或者Navigator.push,視組件不同情況而定
        Navigator.of(context).push(
            MaterialPageRoute(
                builder: (BuildContext context) {
                    return const MyText(
                        arguments: {'kano': "kanokano.cn"},
                    );
                },
            ),
        );
    },
    child: const Text("搜索(路由跳轉)"),
),

創建命名路由#

注意:命名路由在新版 Flutter 文檔中已經被標記為不建議使用

Although named routes can handle deep links, the behavior is always the same and can’t be customized. When a new deep link is received by the platform, Flutter pushes a new onto the Navigator regardless where the user currently is.Route

Flutter also doesn’t support the browser forward button for applications using named routes. For these reasons, we don’t recommend using named routes in most applications.

1. 創建一個名為 MyText 的新路由(這裡直接使用上面的 MyText)

2. 在 main.dart 中使用 Tabs 路由

import 'package:flutter/material.dart';
//普通組件
import './mytext.dart';

void main(List<String> args) {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Test",
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      //1.初始化路由
      initialRoute: '/text1',
      //直接命名路由
      routes: {
        '/text1': (context) => const MyText(),
      },
    );
  }
}

3. 路由跳轉

ElevatedButton(
    onPressed: () {
        //路由
        Navigator.pushNamed(context, '/text1');
    },
    child: const Text("基本路由跳轉text1"),
),

命名路由中的參數傳遞#

總體來說就是這三步:

  1. 配置路由
  2. 初始化路由
  3. 配置 onGenerateRouter
class MyApp extends StatelessWidget {
  //路由傳參 - 1.配置路由 (可以單獨提取出來作為routes.dart
  Map routes = {
    "/": (context) => const Tabs(),
    "/news": (context) => const NewsPage(),
    "/search": (context) => const NewsPage(),
    //帶參數
    "/form": (context, {arguments}) {
      return FormPage(
        arguments: arguments,
      );
    },
    "/shop": (context, {arguments}) {
      return ShopPage(arguments: arguments);
    }
  };

  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Test",
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),

      //2.初始化路由
      initialRoute: '/',

      //路由傳參-3.處理路由(也可以單獨提取出來作為routes.dart
      //配置onGenerateRouter(我覺得這是一個攔截器)
      onGenerateRoute: (RouteSettings settings) {
        print(settings); //路由傳值信息
        print(settings.arguments); //傳的參數
        print(settings.name); //路由名
        final String? name = settings.name;
        final Function? pageCoutentBuilder = routes[name];
        if (pageCoutentBuilder != null) {
          //有參的情況
          if (settings.arguments != null) {
            final Route route = MaterialPageRoute(
              builder: (context) =>
                  pageCoutentBuilder(context, arguments: settings.arguments),
            );
            return route;
          } else {
            //無參的情況
            final Route route = MaterialPageRoute(
              builder: (context) => pageCoutentBuilder(context),
            );
            return route;
          }
        }
        return null;
      },
    );
  }
}

4. 路由跳轉附帶傳值

ElevatedButton(
    onPressed: () {
        //路由
        Navigator.pushNamed(context, '/form',arguments: {"kano": "kanokano"});
    },
    child: const Text("命名路由傳值form"),
),

返回上級路由#

只需要使用

Navigator.pop(context);
//或者
Navigator.of(context).pop()

替換路由#

當我們不想一步一步返回的時候,就可以使用路由的替換模式 (跳轉頁面並銷毀當前頁面)

Navigator.of(context).pushReplacementNamed('/xxx')
//or
Navigator.pushReplacementNamed(context,'/xxx')

路由跳轉風格設置#

Material 組件庫中提供了一個MaterialPageRoute組件,它可以使用和平台風格一致的路由切換動畫,如在 iOS 上會左右滑動切換,而在 Android 上會上下滑動切換,CupertinoPageRoute是 Cupertino 組件庫提供的 iOS 風格的路由切換組件,如果在 Android 上也想使用左右切換風格,可以使用CupertinoPageRoute

1. 引入

import 'package:flutter/cupertino.dart';

2. 修改MaterialPageRouteCupertinoPageRoute

// import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_application_1/pages/form.dart';
import 'package:flutter_application_1/pages/news.dart';
import 'package:flutter_application_1/pages/tabs/shop.dart';
import '../pages/tabs.dart';

//路由傳參 - 1.配置路由(可以單獨提取出來作為routes.dart
Map routes = {
  "/": (context) => const Tabs(),
  "/news": (context) => const NewsPage(),
  "/search": (context) => const NewsPage(),
  //帶參數
  "/form": (context, {arguments}) {
    return FormPage(
      arguments: arguments,
    );
  },
  "/shop": (context, {arguments}) {
    return ShopPage(arguments: arguments);
  }
};
var onGenerateRoute = (RouteSettings settings) {
  final String? name = settings.name;
  final Function? pageCoutentBuilder = routes[name];
  if (pageCoutentBuilder != null) {
    //有參
    if (settings.arguments != null) {
      final Route route = CupertinoPageRoute(
        builder: (context) =>
            pageCoutentBuilder(context, arguments: settings.arguments),
      );
      return route;
    } else {
      //無參
      final Route route = CupertinoPageRoute(
        builder: (context) => pageCoutentBuilder(context),
      );
      return route;
    }
  }
  return null;
};
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。