- 建立导航组件
- 理解有状态组件和无状态组件
- VScode 添加Awesome Flutter Snippets 插件 - 快速生成页面代码
- 数组..add() 方法
- onTap() 底部导航点击事件
- currentIndex 底部导航组件选择高亮
我们经常可以发现移动端的布局形式,喜欢在底部有一个类型的导航,一般包括首页,分类,购物车以及个人中心的选项卡,当点击时分别跳进不同的页面,以京东为例:
首先,我们需要建立一个主页面:
import 'package:flutter/material.dart';
import 'BottomNavigationWidget.dart';
void mian(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'beline App',
theme: ThemeData.light(), //- 主题颜色
home: BottomNavgationWidget()
);
}
}
主页面中,我们在MaterialApp
组件中使用了theme
的属性,是主题属性,那么参数ThemeData.light
是一个亮色.还有其他属性可以参考API
这里我们新建了一个组件BottomNavigationWidget.dart
,直接在home中放置.
接下来,我们需要建立BottomNavigationWidget.dart
这里需要了解一下无状态组件(Stateless widget
)和有状态组件(Stateless widget
)
无状态组件 or 有状态组件
我们前面写的class
都是继承自StatelessWidget
无状态组件.这里先对状态组件做一个简单的区分,后续会详细讲
-
Stateful widget
可以拥有状态,这些状态在widget
生命周期中是可以变的,而Stateless widget
是不可变的。 - Stateful widget至少由两个类组成:
- 一个
StatefulWidget
类。 - 一个
State
类;StatefulWidget
类本身是不变的,但是State
类中持有的状态在widget
生命周期中可能会发生变化。
- 一个
_BottomNavgationWidgetState
类是BottomNavgationWidget
类对应的状态类. _BottomNavgationWidgetState
类中并没有build方法,取而代之的是,build方法被挪到了BottomNavgationWidget
方法中
Awesome Flutter Snippets 插件 - 快速生成页面代码
这里如果我们安装了VScode插件Awesome Flutter Snippets
就可以通过命令stful
直接生成
这里把插件的图也截出来,避免下载错误
接下来我们需要在
_BottomNavgationWidgetState
中写我们的地步导航,和普通的类的写法并没有特别的区别,我们需要retuen
一个Scaffold()
,里面装一个bottomNavigationBar: BottomNavigationBar()
,这个就是底部导航组件,然后通过items中传入widget数组,每个对应一个下面的导航按钮BottomNavigationBarItem()
.可以分别设置icons()
图标和title属性.
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: Colors.blue,
),
title: Text(
'首页',
style:TextStyle(color: Colors.blue)
)
),
]
),
完整代码如下:
import 'package:flutter/material.dart';
//- 动态Widget stful
class BottomNavgationWidget extends StatefulWidget {
@override
_BottomNavgationWidgetState createState() => _BottomNavgationWidgetState();
}
class _BottomNavgationWidgetState extends State {
final _BottomNavgationColor = Colors.blue;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: _BottomNavgationColor,
),
title: Text(
'首页',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.donut_large,
color: _BottomNavgationColor,
),
title: Text(
'分类',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
color: _BottomNavgationColor,
),
title: Text(
'发现',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.shop,
color: _BottomNavgationColor,
),
title: Text(
'购物车',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
color: _BottomNavgationColor,
),
title: Text(
'我的',
style:TextStyle(color: _BottomNavgationColor)
)
)
]
),
);
}
}
然后我们运行虚拟机,看一下底部导航栏的效果:
..add() 方法
我们前面已经把底部导航已经显示出来了,还不能点击.我们需要简单的建5个页面,用于底部导航的跳转.
5个简单的页面都类似下面的结构,只是简单的一个Text组件用于区分页面
home.dart
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home Pages')),
body: Center(
child: Text('Home Pages'),
)
);
}
}
把这5个页面分别引入底部组件的dart
import 'pages/home.dart';
import 'pages/shop.dart';
import 'pages/usercenter.dart';
import 'pages/faxian.dart';
import 'pages/fenlei.dart';
先在State
类中声明一个list
数组,此时我们可以使用..add()
方法,分别把各个组件添加到pagelist
变量中
void initState() {
//- 通过..add()方法添加各个组件到pagelist
pagelist
..add(HomeScreen())
..add(FenLeiScreen())
..add(FaxianScreen())
..add(ShopScreen())
..add(UserCenterScreen());
super.initState();
}
onTap() 底部导航点击事件
我们前面已经把各个页面引入到底部导航菜单,这个时候,我们需要进行切换功能.
首先,在State类中声明一个变量_currentIndex
用于存放指定使用pagelist变量中的组件
然后通过给底部导航栏添加事件,这里需要传入index
,获取点击的是第几个,并赋值给_currentIndex
变量
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
我们在前面引入了底部导航,并没有引入body
,此时有页面了,我们可以加上,并通过下标返回pagelist
中存放的页面组件显示的body上
body: pagelist[_currentIndex],
_currentIndex 底部导航组件选择高亮
在底部导航组件中有一个属性,当你选中这个组件的时候,会有选中样式
currentIndex: _currentIndex,
完整代码:
import 'package:flutter/material.dart';
import 'pages/home.dart';
import 'pages/shop.dart';
import 'pages/usercenter.dart';
import 'pages/faxian.dart';
import 'pages/fenlei.dart';
//- 动态Widget stful
class BottomNavgationWidget extends StatefulWidget {
@override
_BottomNavgationWidgetState createState() => _BottomNavgationWidgetState();
}
class _BottomNavgationWidgetState extends State {
final _BottomNavgationColor = Colors.blue;
int _currentIndex = 0;
List pagelist = List();
@override
void initState() {
//- 通过..add()方法添加各个组件到pagelist
pagelist
..add(HomeScreen())
..add(FenLeiScreen())
..add(FaxianScreen())
..add(ShopScreen())
..add(UserCenterScreen());
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: pagelist[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: _BottomNavgationColor,
),
title: Text(
'首页',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.donut_large,
color: _BottomNavgationColor,
),
title: Text(
'分类',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.search,
color: _BottomNavgationColor,
),
title: Text(
'发现',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.shop,
color: _BottomNavgationColor,
),
title: Text(
'购物车',
style:TextStyle(color: _BottomNavgationColor)
)
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
color: _BottomNavgationColor,
),
title: Text(
'我的',
style:TextStyle(color: _BottomNavgationColor)
)
)
],
currentIndex: _currentIndex,
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}