flutter开发实战-实现自定义bottomNavigationBar样式awesome_bottom_bar
在开发过程中,需要自定义bottomNavigationBar样式,可以自定义实现,这里使用的是awesome_bottom_bar库
一、awesome_bottom_bar
在pubspec.yaml中引入awesome_bottom_bar
dart
awesome_bottom_bar: ^1.2.2
二、实现自定义bottomNavigationBar
切换界面使用PageView.builder
PageView 是一个非常重要的组件。比如大多数 App 都包含 Tab 换页效果、图片轮动以及抖音上下滑页切换视频功能等等都可以使用PageView来实现
dart
PageView({
Key? key,
this.scrollDirection = Axis.horizontal, // 滑动方向
this.reverse = false,
PageController? controller,
this.physics,
List<Widget> children = const <Widget>[],
this.onPageChanged,
//每次滑动是否强制切换整个页面,如果为false,则会根据实际的滑动距离显示页面
this.pageSnapping = true,
//主要是配合辅助功能用的,后面解释
this.allowImplicitScrolling = false,
//后面解释
this.padEnds = true,
})
切换界面使用PageView.builder,当点击不同的tab时候,可以使用PageController进行切换
dart
PageView.builder(
itemBuilder: (BuildContext context, int index) {
return KeepAliveWrapper(
child: subMainPages[index], keepAlive: true);
},
itemCount: subMainPages.length,
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
onPageChanged: (index) {
_selectedIndex = index;
_animationControllerList[_selectedIndex!].forward();
_animationControllerList[_lastSelectedIndex!].reverse();
},
),
),
使用默认效果的bottomNavigationBar
dart
bottomNavigationBar: BottomBarDefault(
items: buildTabItems(context),
backgroundColor: Colors.white,
color: Colors.black87,
colorSelected: Colors.amber,
indexSelected: _selectedIndex,
duration: Duration(milliseconds: 200),
onTap: (int index) => setState(() {
_lastSelectedIndex = _selectedIndex;
_pageController.jumpToPage(index);
}),
),
当需要特殊样式的bottomNavigationBar,时候,比如如下点击后会突出的三角形样式
dart
bottomNavigationBar: BottomBarInspiredInside(
items: [
TabItem(
icon: Icons.home_outlined,
title: S.of(context).home,
),
TabItem(
icon: Icons.qr_code_scanner_outlined,
title: S.of(context).qrScan,
),
TabItem(
icon: Icons.nature_outlined,
title: S.of(context).mine,
count: Container(
padding: EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid,
),
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
// gradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// Colors.red.withOpacity(0.5),
// Colors.red.withOpacity(0.3),
// Colors.red.withOpacity(1.0),
// ],
// ),
),
child: Text(
"99",
style: TextStyle(
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.w500),
),
),
)
],
backgroundColor: Colors.lightBlue,
color: Colors.white,
colorSelected: Colors.white,
indexSelected: _selectedIndex,
duration: Duration(milliseconds: 200),
onTap: (int index) => setState(() {
_pageController.jumpToPage(index);
}),
itemStyle: ItemStyle.hexagon,
chipStyle:
const ChipStyle(isHexagon: true, background: Colors.blueAccent),
),
完整实例代码如下
dart
class MainTabNavigator extends StatefulWidget {
const MainTabNavigator({Key? key}) : super(key: key);
@override
State<MainTabNavigator> createState() => _MainTabNavigatorState();
}
class _MainTabNavigatorState extends State<MainTabNavigator>
with TickerProviderStateMixin {
PageController _pageController = PageController();
int _selectedIndex = 0;
late DateTime _lastPressed;
List<Widget> subMainPages = [];
late List<AnimationController> _animationControllerList;
late List<Animation<double>> _animationList;
int? _lastSelectedIndex = 0;
@override
void initState() {
// 设置默认的
subMainPages = mainPages;
super.initState();
_animationControllerList = List<AnimationController>.empty(growable: true);
_animationList = List<Animation<double>>.empty(growable: true);
for (int i = 0; i < subMainPages.length; ++i) {
_animationControllerList.add(AnimationController(
duration: Duration(milliseconds: 200), vsync: this));
_animationList.add(Tween(begin: 0.0, end: 5.0)
.chain(CurveTween(curve: Curves.ease))
.animate(_animationControllerList[i]));
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_animationControllerList[_selectedIndex!].forward();
});
}
void animationDispose() {
for (int i = 0; i < subMainPages.length; ++i) {
_animationControllerList[i].dispose();
}
}
@override
void dispose() {
// TODO: implement dispose
animationDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: WillPopScope(
onWillPop: () async {
if (_lastPressed == null ||
DateTime.now().difference(_lastPressed) > Duration(seconds: 1)) {
//两次点击间隔超过1秒则重新计时
_lastPressed = DateTime.now();
return false;
}
return true;
},
child: PageView.builder(
itemBuilder: (BuildContext context, int index) {
return KeepAliveWrapper(
child: subMainPages[index], keepAlive: true);
},
itemCount: subMainPages.length,
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
onPageChanged: (index) {
_selectedIndex = index;
_animationControllerList[_selectedIndex!].forward();
_animationControllerList[_lastSelectedIndex!].reverse();
},
),
),
// bottomNavigationBar: BottomBarDefault(
// items: buildTabItems(context),
// backgroundColor: Colors.white,
// color: Colors.black87,
// colorSelected: Colors.amber,
// indexSelected: _selectedIndex,
// duration: Duration(milliseconds: 200),
// onTap: (int index) => setState(() {
// _lastSelectedIndex = _selectedIndex;
// _pageController.jumpToPage(index);
// }),
// ),
bottomNavigationBar: BottomBarInspiredInside(
items: [
TabItem(
icon: Icons.home_outlined,
title: S.of(context).home,
),
TabItem(
icon: Icons.qr_code_scanner_outlined,
title: S.of(context).qrScan,
),
TabItem(
icon: Icons.nature_outlined,
title: S.of(context).mine,
count: Container(
padding: EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid,
),
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
// gradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// Colors.red.withOpacity(0.5),
// Colors.red.withOpacity(0.3),
// Colors.red.withOpacity(1.0),
// ],
// ),
),
child: Text(
"99",
style: TextStyle(
fontSize: 10,
color: Colors.white,
fontWeight: FontWeight.w500),
),
),
)
],
backgroundColor: Colors.lightBlue,
color: Colors.white,
colorSelected: Colors.white,
indexSelected: _selectedIndex,
duration: Duration(milliseconds: 200),
onTap: (int index) => setState(() {
_pageController.jumpToPage(index);
}),
itemStyle: ItemStyle.hexagon,
chipStyle:
const ChipStyle(isHexagon: true, background: Colors.blueAccent),
),
// bottomNavigationBar: FlashyTabBar(
// selectedIndex: _selectedIndex,
// showElevation: true,
// onItemSelected: (index) => setState(() {
// _pageController.jumpToPage(index);
// }),
// items: [
// FlashyTabBarItem(
// icon: Icon(Icons.home_outlined),
// title: Text(S.of(context).home),
// ),
// FlashyTabBarItem(
// icon: Icon(Icons.qr_code_scanner_outlined),
// title: Text(S.of(context).qrScan),
// ),
// FlashyTabBarItem(
// icon: Icon(Icons.nature_outlined),
// title: Text(S.of(context).mine),
// ),
// ],
// ), // bottomNavigationBar: BottomNavigationBar(
);
}
List<TabItem> buildTabItems(BuildContext context) {
TabItem homeItem = TabItem(
icon: Icons.home_outlined,
title: S.of(context).home,
count: buildTabItem(context, 0),
);
TabItem qsItem = TabItem(
icon: Icons.qr_code_scanner_outlined,
title: S.of(context).qrScan,
count: buildTabItem(context, 1),
);
TabItem discoveryItem = TabItem(
icon: Icons.location_searching_outlined,
title: S.of(context).discovery,
count: buildTabItem(context, 2),
);
TabItem mineItem = TabItem(
icon: Icons.nature_outlined,
title: S.of(context).mine,
count: buildTabItem(context, 3),
);
return [homeItem, qsItem, discoveryItem, mineItem];
}
Widget buildTabItem(BuildContext context, int index) {
return AnimatedBuilder(
animation: _animationList[index],
builder: (BuildContext context, Widget? child) {
return Container(
margin: EdgeInsets.only(
top: _animationList[index].value,
),
child: child,
);
},
child: buildTabItemCount(context),
);
}
Widget buildTabItemCount(BuildContext context) {
return Container(
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid,
),
color: Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(30.0),
),
// gradient: LinearGradient(
// begin: Alignment.topLeft,
// end: Alignment.bottomRight,
// colors: [
// Colors.red.withOpacity(0.5),
// Colors.red.withOpacity(0.3),
// Colors.red.withOpacity(1.0),
// ],
// ),
),
child: const Text(
"99",
style: TextStyle(
fontSize: 10, color: Colors.white, fontWeight: FontWeight.w500),
),
);
}
}
三、小结
flutter开发实战-自定义bottomNavigationBar样式。
https://blog.csdn.net/gloryFlow/article/details/132761946
学习记录,每天不停进步。