Flutter 路由

路由简介


Route
一个路由是一个屏幕或页面的抽象

Navigator
管理路由的组件,Navigator 可以通过路由入栈和出栈来实现页面之间的跳转

常用属性:
initialRoute:初始路由,即默认页面
onGenerateRoute:动态路由(根据规则,匹配动态路由)
onUnknownRoute:未知路由,也就是404
routes:路由集合

匿名路由

Navigator
  push():跳转到指定组件
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => 组件名称(),
    settings: const RouteSettings(
      name: String, // 路由名称
      arguments: {
        String: dynamic, // 参数
      },
    ),
  )
)

 

pop():回退
Navigator.pop(context)

 

示例:

import 'package:flutter/material.dart';
import '08_navigator/navigator_01_anonymous.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      // home: Home(),
      // 声明路由
      routes: {
        'home': (context) => const Home(),
        'product': (context) => const Product(),
      },
      // 初始路由
      initialRoute: 'home',
      debugShowCheckedModeBanner: false,
    );
  }
}
import 'package:flutter/material.dart';

// 首页
class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('匿名路由'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          ElevatedButton(
            onPressed: () {
              // 匿名路由跳转 --基本用法
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const Product()),
              );
            },
            child: const Text('跳转到商品页面'),
          ),
          ElevatedButton(
            onPressed: () {
              // 匿名路由跳转 -- 传参方法 1
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const Product(),
                  settings: const RouteSettings(
                    name: '带参数的商品页面', // 修改路由名称
                    arguments: {
                      'userName': 'zhangsan',
                      'age': 23,
                    },
                  ),
                ),
              );
            },
            child: const Text('跳转带传参 settings'),
          ),
          ElevatedButton(
            onPressed: () {
              // 匿名路由跳转-- 传参方法 2
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const ProductDetail(id: '123'),
                ),
              );
            },
            child: const Text('跳转带传参 属性'),
          ),
        ],
      ),
    );
  }
}

// 商品页
class Product extends StatelessWidget {
  const Product({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    dynamic settings = ModalRoute.of(context)?.settings;
    print('settings: $settings');
    return Scaffold(
      appBar: AppBar(
        // 传参方法 1:通过 settings 接收参数
        title: Text(settings?.name == null ? '商品页面' : settings.name),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          Text(
            // 传参方法 1:通过 settings 接收参数
            '主页传递的参数是: ${settings.arguments}',
            style: const TextStyle(
              fontSize: 26,
              color: Colors.red,
            ),
          ),
          ElevatedButton(
            onPressed: () {
              // 回退
              return Navigator.pop(context);
            },
            child: const Text('返回'),
          ),
        ],
      ),
    );
  }
}

// 商品详情
class ProductDetail extends StatelessWidget {
  final String id;
  const ProductDetail({
    Key? key,
    required this.id,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('商品详情'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          // 传参方法 2:通过 类属性 接收参数
          Text(
            '主页传递的参数是: $id',
            style: const TextStyle(
              fontSize: 26,
              color: Colors.red,
            ),
          ),
          ElevatedButton(
            onPressed: () {
              // 回退
              return Navigator.pop(context);
            },
            child: const Text('返回'),
          ),
        ],
      ),
    );
  }
}

 

命名路由

(1)、声明路由
routes:路由表(Map类型)
initialRoute:初始路由
onUnknownRoute:未知路由 - 404

(2)、跳转到命名路由
Navigator.pushNamed(context, '路由名称');

 

示例:

import 'package:flutter/material.dart';
import '08_navigator/navigator_02_namedRoute.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      // home: Home(),
      // 声明路由
      routes: {
        'home': (context) => const Home(),
        'product': (context) => const Product(),
      },
      // 初始路由
      initialRoute: 'home',
      // 未知路由
      onUnknownRoute: (RouteSettings setting) => MaterialPageRoute(
        builder: (context) => const UnknownPage(),
      ),
      // 动态路由
      debugShowCheckedModeBanner: false,
    );
  }
}
import 'package:flutter/material.dart';

// 首页
class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('命名路由'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, 'product'),
            child: const Text('跳转到商品页面'),
          ),
          // 命名路由传参
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(
              // 上下文
              context,
              // 路由名称
              'product',
              // 参数
              arguments: <String, dynamic>{
                "title": "我是首页传过来的参数",
                "age": 28,
                "viewFlag": true,
              },
            ),
            child: const Text('跳转到商品页面带入参'),
          ),
          // 未知路由跳转
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, 'user'),
            child: const Text('跳转到不存在的路由'),
          ),
        ],
      ),
    );
  }
}

// 商品
class Product extends StatelessWidget {
  const Product({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // 接收传参,可能是 null
    final arguments = ModalRoute.of(context)!.settings.arguments;
    return Scaffold(
      appBar: AppBar(
        title: const Text('商品页面'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          // 参数
          Text(
            '接收的参数是:$arguments',
            style: const TextStyle(
              fontSize: 26,
              color: Colors.red,
            ),
          ),
          ElevatedButton(
            onPressed: () {
              // 返回
              return Navigator.pop(context);
            },
            child: const Text('返回'),
          )
        ],
      ),
    );
  }
}

// 404
class UnknownPage extends StatelessWidget {
  const UnknownPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('404'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: const Text('页面飞到太空去了……'),
      ),
    );
  }
}

 

动态路由

动态路由是指通过 onGeneratedRoute 属性指定的路由

示例:

import 'package:flutter/material.dart';
import '08_navigator/navigator_03_onGeneratedRoute.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      // home: Home(),
      // 动态路由
      onGenerateRoute: (RouteSettings setting) {
        print('setting: $setting');
        print('当前路径:${setting.name}');
        // 匹配首页 /
        if (setting.name == '/') {
          return MaterialPageRoute(builder: (context) => const Home());
        }
        // 匹配商品页 /product
        if (setting.name == '/product') {
          return MaterialPageRoute(builder: (context) => const Product());
        }
        // 匹配商品详情页 /product/:id
        Uri uri = Uri.parse(setting.name ?? '');
        print('uri: $uri');
        if (uri.pathSegments.length == 2 &&
            uri.pathSegments.first == 'product') {
          String id = uri.pathSegments[1];
          return MaterialPageRoute(builder: (context) => ProductDetail(id: id));
        }
        return MaterialPageRoute(builder: (context) => const UnknownPage());
      },
      debugShowCheckedModeBanner: false,
    );
  }
}
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('命名路由'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, '/product'),
            child: const Text('跳转到商品页面'),
          ),
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, '/product/1'),
            child: const Text('商品1'),
          ),
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, '/product/2'),
            child: const Text('商品2'),
          ),
          // 未知路由跳转
          ElevatedButton(
            // 命名路由跳转
            onPressed: () => Navigator.pushNamed(context, '/product222'),
            child: const Text('跳转到不存在的路由'),
          ),
        ],
      ),
    );
  }
}

// 商品
class Product extends StatelessWidget {
  const Product({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('商品页面'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: ElevatedButton(
          onPressed: () {
            return Navigator.pop(context);
          },
          child: const Text('返回'),
        ),
      ),
    );
  }
}

// 商品详情
class ProductDetail extends StatelessWidget {
  final String id;
  const ProductDetail({
    Key? key,
    required this.id,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('商品详情'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(10),
        children: [
          Text('当前商品的id是 $id'),
          ElevatedButton(
            onPressed: () {
              return Navigator.pop(context);
            },
            child: const Text('返回'),
          ),
        ],
      ),
    );
  }
}

// 404
class UnknownPage extends StatelessWidget {
  const UnknownPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('404'),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: const Text('页面飞到太空去了……'),
      ),
    );
  }
}

 

 

posted @ 2022-05-27 14:07  rogerwu  阅读(302)  评论(0编辑  收藏  举报