Flutter救赎之路一【自定义bottomNavigationBar点击动画】
这是继上次立下敲一个独立 app 的 flag 后实践的第一篇文章。尽量每次新库的使用方法也会在这里记录一下,代码规范优化请大佬指教。
bottomNavigationBar点击动画之 Lottie
Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as json with Bodymovin and renders them natively on mobile! This repository is an unofficial conversion of the Lottie-android library in pure Dart. It works on Android, iOS, macOS, linux, windows and web.
正文
- 效果图
- 直接上代码,
- 只是思路,不要直接用
- icon 是自带的,将就一下,选中状态的动图也是用的 lottie 示例里边的,这里只演示达到的效果
import 'package:beauty/page/discover/discoverPage.dart';
import 'package:beauty/page/history/historyPage.dart';
import 'package:beauty/page/home/homePage.dart';
import 'package:beauty/page/tabbar/BottomNavigationBarItem.dart';
import 'package:beauty/page/userCenter/userCenterPage.dart';
import 'package:flutter/material.dart';
class MyTabbar extends StatefulWidget {
const MyTabbar({Key? key}) : super(key: key);
@override
State<MyTabbar> createState() => _MyTabbarState();
}
class _MyTabbarState extends State<MyTabbar> {
int _currentTopTabIndex = 0;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
final List<Widget> _pageList = <Widget>[
const HomePage(),
const DisCoverPage(),
const HistoryPage(),
const UserCenterPage(),
];
final List<BottomBarItemModel> _bottomTabList = <BottomBarItemModel>[
BottomBarItemModel(
icon: const Icon(Icons.home),
lottie: 'assets/lottie/loading_indicator.json',
title: '首页',
index: 0,
badger: 0),
BottomBarItemModel(
icon: const Icon(Icons.discord),
lottie: 'assets/lottie/loading_indicator.json',
title: '发现',
index: 1,
badger: 0),
BottomBarItemModel(
icon: const Icon(Icons.history),
lottie: 'assets/lottie/loading_indicator.json',
title: '历史',
index: 2,
badger: 0),
BottomBarItemModel(
icon: const Icon(Icons.person),
lottie: 'assets/lottie/loading_indicator.json',
title: '我的',
index: 3,
badger: 0),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pageList[_currentTopTabIndex],
bottomNavigationBar: BottomAppBar(
elevation: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: List.generate(
_bottomTabList.length,
(index) => BottomBarItem(
model: _bottomTabList[index],
onTap: (index) {
setState(() {
_currentTopTabIndex = index;
});
},
selected: _currentTopTabIndex == index,
)))),
);
}
}
class BottomBarItemModel {
final Widget icon;
final String lottie;
final String title;
int index;
int badger;
BottomBarItemModel(
{required this.icon,
required this.lottie,
required this.title,
required this.badger,
required this.index});
}
import 'package:beauty/page/tabbar/tabbar.dart';
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
class BottomBarItem extends StatefulWidget {
final BottomBarItemModel model;
final Function(int) onTap;
final bool selected;
final int badger;
const BottomBarItem(
{Key? key,
this.selected = false,
this.badger = 0,
required this.model,
required this.onTap})
: super(key: key);
@override
State<BottomBarItem> createState() => _BottomBarItemState();
}
class _BottomBarItemState extends State<BottomBarItem> {
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Container(
// ignore: sort_child_properties_last
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(top: 4),
child: Column(
children: [
widget.selected
? SizedBox(
width: 25,
height: 25,
child: Lottie.asset(
widget.model.lottie,
repeat: false,
))
: widget.model.icon,
Text(widget.model.title)
],
)),
Visibility(
visible: widget.model.badger > 0,
child: Positioned(
right: 0,
child: ClipOval(
child: Container(
alignment: Alignment.center,
color: Colors.red,
width: 15,
height: 15,
child: Text(
widget.model.badger.toString(),
style: const TextStyle(color: Colors.white, fontSize: 9),
),
)),
))
],
),
height: 49,
width: 39,
),
onTap: () {
widget.onTap(widget.model.index);
},
);
}
}