FLUTTER学习笔记--路由与导航


一、匿名路由

1.Navigator

  • push(跳转到指定组件)
    • Navigator.push(
      context, MaterialPageRoute(builder: (context) => 组件名称()) )
  • pop(回退)
    • Navigator.pop(context)

2.代码

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
                context, MaterialPageRoute(builder: (context) => Product()));
          },
          child: Text('跳转到商品页面'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("商品页面"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Center(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('返回'),
            ),
          ),
        ));
  }
}

3.效果

08b1c282-6fc5-41f4-baa3-483779abd86f.gif

二、命名路由

1.声明路由

  • routes路由表(Map类型)
  • initialRoute(初始路由)
  • onUnknownRoute(未知路由-404)

2.跳转到命名路由

  • Navigator.pushNamed(context,‘路由名字’)

3.代码

main() {
  runApp(nameRoute());
}

class nameRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      //home: HomePage(),
      //声明命名路由
      routes: {
        'homePage': (context) => homePage(),
        'product': (context) => product(),
      },
      initialRoute: 'homePage',
      onUnknownRoute: (RouteSettings setting) =>
          MaterialPageRoute(builder: (context) => UnknowPage()),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("首页"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Column(
            children: [
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, 'product'),
                child: Text('跳转'),
              ),
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, 'user'),
                child: Text('未知路由'),
              )
            ],
          ),
        ));
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("商品页面"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Center(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('返回'),
            ),
          ),
        ));
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("404"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Center(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('返回'),
            ),
          ),
        ));
  }
}

4.效果

d2a69eea-d0f5-49e7-9cc7-d57624681ab2.gif

三、动态路由

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

2.代码

main() {
  runApp(onGenerateRoute());
}

class onGenerateRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      onGenerateRoute: (RouteSettings setting) {
        //匹配首页 /
        print('当前路径${setting.name}');
        if (setting.name == '/') {
          return MaterialPageRoute(builder: (context) => _homePage());
        }
        if (setting.name == '/product') {
          return MaterialPageRoute(builder: (context) => product());
        }

        //匹配 /product/:id
        var uri = Uri.parse(setting.name.toString());
        print(uri.pathSegments);
        if (uri.pathSegments.length == 2 &&
            uri.pathSegments.first == 'product') {
          var id = uri.pathSegments[1];
          return MaterialPageRoute(builder: (context) => productDetail(id: id));
        }
        return MaterialPageRoute(builder: (context) => UnknowPage());
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("首页"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Column(
            children: [
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, '/product'),
                child: Text('跳转'),
              ),
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, '/product/1'),
                child: Text('商品1'),
              ),
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, '/product/2'),
                child: Text('商品2'),
              ),
              ElevatedButton(
                onPressed: () => Navigator.pushNamed(context, 'user'),
                child: 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("商品详情页"),
        leading: Icon(Icons.menu),
        actions: [Icon(Icons.settings)],
        elevation: 10.0,
        centerTitle: true,
      ),
      body: Center(
        child: Column(children: [
          Text('当前商品的id是${this.id}'),
          ElevatedButton(
            onPressed: () => Navigator.pop(context),
            child: Text('返回'),
          )
        ]),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("商品页面"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Center(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('返回'),
            ),
          ),
        ));
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("404"),
          leading: Icon(Icons.menu),
          actions: [Icon(Icons.settings)],
          elevation: 10.0,
          centerTitle: true,
        ),
        body: Center(
          child: Center(
            child: ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: Text('返回'),
            ),
          ),
        ));
  }
}

3.效果

7a4baf5f-f3c0-4d07-b60b-58d496710f26.gif

四、匿名路由

1.匿名路由

  • 路由中声明参数
    • Navigator.push
  • 组件中接受参数

2.命名路由

  • 路由中声明参数
    • Navigator.pushNamed(context, routename, {arguments}),
  • 组件中接受参数
    • ModalRoute.of(context).settings.arguments

3.代码

class arguments extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     debugShowCheckedModeBanner: false,
     routes: {
       'homePage': (context) => homePage_(),
       'product': (context) => _product(),
       'productDetail': (context) => _productDetail(),
     },
     initialRoute: 'homePage',
     onUnknownRoute: (RouteSettings setting) =>
         MaterialPageRoute(builder: (context) => UnknowPage()),
   );
 }
}

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

 @override
 Widget build(BuildContext context) {
   return Scaffold(
       appBar: AppBar(
         title: const Text("首页"),
         leading: Icon(Icons.menu),
         actions: [Icon(Icons.settings)],
         elevation: 10.0,
         centerTitle: true,
       ),
       body: Center(
         child: Column(
           children: [
             ElevatedButton(
               onPressed: () =>
                   Navigator.pushNamed(context, 'product',
                       arguments: {'title': '我是主页传来的参数'}),
               child: Text('跳转到商品页面'),
             ),
             ElevatedButton(
               onPressed: () =>
                   Navigator.pushNamed(context, 'productDetail',
                       arguments: {'id': 1}),
               child: Text('商品1'),
             ),
             ElevatedButton(
               onPressed: () =>
                   Navigator.pushNamed(context, 'productDetail',
                       arguments: {'id': 2}),
               child: Text('商品2'),
             ),
             ElevatedButton(
               onPressed: () => Navigator.pushNamed(context, 'user'),
               child: Text('未知路由'),
             )
           ],
         ),
       ));
 }
}

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

 @override
 Widget build(BuildContext context) {
   final Map arguments = ModalRoute
       .of(context)
       ?.settings
       .arguments as Map;

   return Scaffold(
     appBar: AppBar(
       title: const Text("商品详情页"),
       leading: Icon(Icons.menu),
       actions: [Icon(Icons.settings)],
       elevation: 10.0,
       centerTitle: true,
     ),
     body: Center(
       child: Column(children: [
         Text('当前商品的id是' + arguments['id'].toString()),
         ElevatedButton(
           onPressed: () => Navigator.pop(context),
           child: Text('返回'),
         )
       ]),
     ),
   );
 }
}

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

 @override
 Widget build(BuildContext context) {
   final Map arguments = ModalRoute
       .of(context)
       ?.settings
       .arguments as Map;

   return Scaffold(
     appBar: AppBar(
       title: const Text("商品页面"),
       leading: Icon(Icons.menu),
       actions: [Icon(Icons.settings)],
       elevation: 10.0,
       centerTitle: true,
     ),
     body: Center(
       child: Column(
         children: [
           Text('接受的参数是' + arguments['title']),
           ElevatedButton(
             onPressed: () => Navigator.pop(context),
             child: Text('返回'),
           )
         ],
       ),
     ),
   );
 }
}

4.效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xTfzpG18-1673541095447)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c94c4bd0ae2429a8741af9be2381e8a~tplv-k3u1fbpfcp-watermark.image?)]

五、Drawer导航

1.Scaffold

  • drawer(左侧抽屉菜单)
  • endDrawer(右侧抽屉菜单)

2.UserAccountDrawerHeader

  • 抽屉菜单头部组件

3.AboutListTitle

  • 关于弹窗

4.代码

class drawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Drawer"),
        leading: Icon(Icons.menu),
        actions: [Icon(Icons.settings)],
        elevation: 0.0,
        centerTitle: true,
      ),
      body: homepage(),
      drawer: DrawerList(),
      endDrawer: DrawerList(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text('Home'),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Drawer(
        child: ListView(
          padding: EdgeInsets.all(0),
          children: [
            UserAccountsDrawerHeader(
              accountName: Text('hhh'),
              accountEmail: Text('skd@qq.com'),
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('images/1.png'),
                  fit: BoxFit.cover,
                ),
              ),
              currentAccountPicture: CircleAvatar(
                backgroundImage: AssetImage('images/2.png'),
              ),
            ),
            Divider(
              thickness: 2,
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('设置'),
              trailing: Icon(Icons.arrow_forward_ios),
            ),
            Divider(
              thickness: 2,
            ),
            ListTile(
              leading: Icon(Icons.account_balance),
              title: Text('余额'),
              trailing: Icon(Icons.arrow_forward_ios),
            ),
            Divider(
              thickness: 2,
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('我的'),
              trailing: Icon(Icons.arrow_forward_ios),
            ),
            Divider(
              thickness: 2,
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('回退'),
              onTap: () => Navigator.pop(context),
              trailing: Icon(Icons.arrow_forward_ios),
            ),
            AboutListTile(
              child: Text('关于'),
              applicationName: '你的应用名称',
              applicationVersion: '1.0.0',
              icon: CircleAvatar(
                child: Text('aaa'),
              ),
              applicationLegalese: '你的应用名称',
              aboutBoxChildren: [
                Text('条例一:'),
                Text('条例一:'),
              ],
              applicationIcon: Image.asset(
                'images/3.jpg',
                width: 50,
                height: 50,
              ),
            )
          ],
        ));
  }
}

5.效果

8b333e57-b3fe-4ae4-a40f-8e1cc23c71e7.gif

六、BottomNavigationBar导航

1.items

  • 包含导航(BottomNavigationBarItem)的列表

2.currentIndex

  • 当前导航索引

3.type

  • 导航类型(BottomNavigationBarType)

4.onTap()

  • 导航的点击事件(一般会更新导航索引)

5.代码

class bottomNavigatorBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: hOme(),
    );
  }
}

class hOme extends StatefulWidget {
  const hOme({Key? key}) : super(key: key);

  @override
  State<hOme> createState() => _hOmeState();
}

class _hOmeState extends State<hOme> {
  final List<BottomNavigationBarItem> bottomNavItems = [
    BottomNavigationBarItem(
      backgroundColor: Colors.blue,
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.green,
      icon: Icon(Icons.message),
      label: '消息',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.amber,
      icon: Icon(Icons.shopping_cart),
      label: '购物车',
    ),
    BottomNavigationBarItem(
      backgroundColor: Colors.red,
      icon: Icon(Icons.person),
      label: '我的',
    ),
  ];

  final pages = [
    Center(
      child: Text('Home', style: TextStyle(fontSize: 50),),
    ),
    Center(
      child: Text('Message', style: TextStyle(fontSize: 50),),
    ),
    Center(
      child: Text('Shopping cart', style: TextStyle(fontSize: 50),),
    ),
    Center(
      child: Text('Profile', style: TextStyle(fontSize: 50),),
    )
  ];

  late int currentIndex;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    currentIndex = 0;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("底部导航"),
        leading: Icon(Icons.menu),
        actions: [Icon(Icons.settings)],
        elevation: 0.0,
        centerTitle: true,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: bottomNavItems,
        currentIndex: currentIndex,
        //type: BottomNavigationBarType.fixed,
        type: BottomNavigationBarType.shifting,
        onTap: (index) {
          _changePage(index);
        },
      ),
      body: pages[currentIndex],
    );
  }

  void _changePage(int index) {
    if (index != currentIndex) {
      setState(() {
        currentIndex = index;
      });
    }
  }
}

6.效果

3fe461e8-1803-4c64-a05b-a3492afe9b96.gif

七、Tab导航

1.DefaultTabController(整个Tab导航的容器)

  • length(声明导航数量)
  • child(指定子组件)

2.TabBar(导航菜单)

  • tabs(导航菜单数组)

3.TabBarView(导航页面)

  • children(多个导航页面内容)

4.代码

class tabDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: tabhome(),
    );
  }
}

class tabhome extends StatelessWidget {
  //菜单数组
  final List<Widget> _tabs = [
    Tab(text: '首页', icon: Icon(Icons.home)),
    Tab(text: '添加', icon: Icon(Icons.add)),
    Tab(text: '搜索', icon: Icon(Icons.search)),
  ];

  //页面数组
  final List<Widget> _tabViews = [
    Icon(Icons.home, size: 120, color: Colors.red),
    Icon(Icons.add, size: 120, color: Colors.green),
    Icon(Icons.search, size: 120, color: Colors.black),
  ];

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: _tabs.length,
        child: Scaffold(
            appBar: AppBar(
              title: const Text("Tab"),
              leading: Icon(Icons.menu),
              actions: [Icon(Icons.settings)],
              elevation: 10.0,
              centerTitle: true,
              bottom: TabBar(
                tabs: _tabs,
                labelColor: Colors.yellow,
                unselectedLabelColor: Colors.black45,
                indicatorSize: TabBarIndicatorSize.tab,
                indicatorColor: Colors.yellow,
                indicatorWeight: 10,
              ),
            ),
            body:TabBarView(
              children: _tabViews,
            ),
          bottomNavigationBar: TabBar(
            tabs: _tabs,
            labelColor: Colors.blue,
            unselectedLabelColor: Colors.black45,
          ),
        )
    );
  }
}

5.效果

3dadd31c-ade6-45b1-a2c6-ba66bfe16653.gif

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值