flutter 开发笔记(二):路由

254 阅读2分钟

路由是一个应用程序中不可或缺的功能,它负责管理页面的导航和切换。本文将简要介绍 Flutter 的路由功能,并提供一个可复现的示例代码,能更好地理解和使用路由

简介

首先介绍一个概念,应用构建器(app builders),通常路由就是在里面设置的,常用的有以下几种:

  • MaterialApp:使用 Material Design 组件构建应用,主要用于 Android 以及跨平台应用
  • CupertinoApp:使用 Cupertino (iOS) 组件构建应用,主要用于提供 iOS 风格的用户界面
  • WidgetsApp:这是一个更基础的应用构建器,适用于需要高度自定义的应用界面

上述的构建器提供了以下两种方式来设置路由:

  • routes 参数:用于设置静态路由,适用于不需要参数或参数固定的页面
  • onGenerateRoute 参数:用于设置动态路由,适用于需要传递动态参数的页面,或根据不同条件动态生成页面的场景

示例

以一个 To-Do List 为例,创建两个文件,main.dart 和 details_page.dart

main.dart 文件,定义首屏路由的方式有两种,一种是赋值 home 参数,第二种是 routes 参数配置 / 路由,第一种的优先级最高;可以看到,details 路由需要接收两个参数,因此只能通过 onGenerateRoute 配置动态路由;同时,也可以校验 settings.arguments,根据情况跳转不同的页面

import 'package:flutter/material.dart';
import 'details_page.dart'; // 导入 details_page.dart 文件

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter To-Do Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomePage(),
      // routes: {
      //   '/': (context) => const HomePage(),
      // },
      onGenerateRoute: (settings) {
        if (settings.name == '/details') {
          final args = settings.arguments as DetailsPageArguments;
          return MaterialPageRoute(
            builder: (context) {
              return DetailsPage(
                title: args.title,
                description: args.description,
              );
            },
          );
        }
        return null;
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    // 定义待办事项列表
    final List<DetailsPageArguments> items = [
      DetailsPageArguments(
          'Buy Groceries', 'Remember to buy milk, eggs, and bread.'),
      DetailsPageArguments(
          'Complete Flutter Project', 'Finish the UI design and fix bugs.'),
      // 可以添加更多项目
    ];

    return Scaffold(
      appBar: AppBar(
        title: const Text('To-Do List'),
      ),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          final item = items[index];
          return ListTile(
            title: Text(item.title),
            onTap: () {
              Navigator.pushNamed(
                context,
                '/details',
                arguments: item,
              );
            },
          );
        },
      ),
    );
  }
}

class DetailsPageArguments {
  final String title;
  final String description;

  DetailsPageArguments(this.title, this.description);
}

details_page.dart 文件

import 'package:flutter/material.dart';

class DetailsPage extends StatelessWidget {
  final String title;
  final String description;

  const DetailsPage(
      {super.key, required this.title, required this.description});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              title,
              style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            Text(
              description,
              style: const TextStyle(fontSize: 16),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: const Text('Back'),
            ),
          ],
        ),
      ),
    );
  }
}

上述点击跳转和回退都是通过 Navigator 类实现的,文档可参考 api.flutter.dev/flutter/wid…