1,创建单个导航图标文字组件文件
import 'package:flutter/material.dart';
class NavigationIconView {
// 创建两个属性,一个是 用来展示 icon, 一个是动画处理
final BottomNavigationBarItem item;
final AnimationController controller;
// 类似于 java 中的构造方法
// 创建 NavigationIconView 需要传入三个参数, icon 图标,title 标题, TickerProvider
NavigationIconView({Widget icon, Widget title, TickerProvider vsync})
: item = new BottomNavigationBarItem(
icon: icon,
title: title,
),
controller = new AnimationController(
duration: kThemeAnimationDuration, // 设置动画持续的时间
vsync: vsync // 默认属性和参数
);
}
2,创建4个页面home,course,book,my,以下只列出其中一个页面代码,其他都一样
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget{
@override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('首页'),
actions: <Widget>[
new Container()
],
),
body: new Center(
child: null,
),
),
);
}
}
3,创建index页面,用来渲染导航的布局
import 'package:flutter/material.dart';
import 'package:flutter_app/home/home_page.dart';
import 'package:flutter_app/course/course_page.dart';
import 'package:flutter_app/book/book_page.dart';
import 'package:flutter_app/my/my_page.dart';
import 'package:flutter_app/navigation_icon_view.dart'; // 如果是在同一个包的路径下,可以直接使用对应的文件名
// 创建一个 带有状态的 Widget Index
class Index extends StatefulWidget {
// 固定的写法
@override
State<StatefulWidget> createState() => new _IndexState();
}
// 要让主页面 Index 支持动效,要在它的定义中附加mixin类型的对象TickerProviderStateMixin
class _IndexState extends State<Index> with TickerProviderStateMixin {
int _currentIndex = 0; // 当前界面的索引值
List<NavigationIconView> _navigationViews; // 底部图标按钮区域
List<StatefulWidget> _pageList; // 用来存放我们的图标对应的页面
StatefulWidget _currentPage; // 当前的显示页面
// 定义一个空的设置状态值的方法
void _rebuild() {
setState(() {});
}
@override
void initState() {
super.initState();
// 初始化导航图标
_navigationViews = <NavigationIconView>[
new NavigationIconView(
icon: new Icon(Icons.home), title: new Text("首页"), vsync: this),
// vsync 默认属性和参数
new NavigationIconView(
icon: new Icon(Icons.videocam),
title: new Text("课程"),
vsync: this),
new NavigationIconView(
icon: new Icon(Icons.book), title: new Text("书籍"), vsync: this),
new NavigationIconView(
icon: new Icon(Icons.perm_identity),
title: new Text("我的"),
vsync: this),
];
// 给每一个按钮区域加上监听
for (NavigationIconView view in _navigationViews) {
view.controller.addListener(_rebuild);
}
// 将我们 bottomBar 上面的按钮图标对应的页面存放起来,方便我们在点击的时候
_pageList = <StatefulWidget>[
HomePage(),
CoursePage(),
BookPage(),
MyPage()
];
_currentPage = _pageList[_currentIndex];
}
@override
Widget build(BuildContext context) {
// 声明定义一个 底部导航的工具栏
final BottomNavigationBar bottomNavigationBar = new BottomNavigationBar(
items: _navigationViews
.map((NavigationIconView navigationIconView) =>
navigationIconView.item)
.toList(), // 添加 icon 按钮
currentIndex: _currentIndex, // 当前点击的索引值
type: BottomNavigationBarType.fixed, // 设置底部导航工具栏的类型:fixed 固定
onTap: (int index) {
// 添加点击事件
setState(() {
// 点击之后,需要触发的逻辑事件
_navigationViews[_currentIndex].controller.reverse();
_currentIndex = index;
_navigationViews[_currentIndex].controller.forward();
_currentPage = _pageList[_currentIndex];
});
},
);
return new MaterialApp(
home: new Scaffold(
body: new Center(child: _currentPage // 动态的展示我们当前的页面
),
bottomNavigationBar: bottomNavigationBar, // 底部工具栏
),
theme: new ThemeData(
primarySwatch: Colors.blue, // 设置主题颜色
),
);
}
}
4,main.dart代码如下
import 'package:flutter/material.dart';
import 'package:flutter_app/index/Index.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.red,
),
home: Index(),
);
}
}
5,测试运行

文章永久链接:https://tech.souyunku.com/43179