Flutter 系统自带的BottomNavigationBar,在点击时item会有一个水波纹效果,产品并不想要这个(实际上这个水波纹有的时候还会卡住没法消失)。
网上暂时没有找到现成的,因此就本身撸一个。
PS:经过继承InteractiveInkFeature,也能够去除一些widget自带的水波纹(使用方法能够参考demo里的NoInkWellFactory类文件),不过bottom nav这里无法使用。
复制代码
首先总体结构,咱们参照系统的,子Item的状态咱们经过Provider进行管理,先建立一个BottomNavBarNoInk.
代码以下(说明我尽可能写在注释里方便阅读):
复制代码
class BottomNavBarNoInk extends StatefulWidget{
IndexModel indexModel;
final width;
final height;
List<BottomNavigationBarItem> items;
int currentIndex;
ValueChanged<int> onTap;
BottomNavBarNoInk({@required this.width
,@required this.
height,@required this.items,
this.currentIndex,this.onTap}) : indexModel = IndexModel(currentIndex);
@override
State<StatefulWidget> createState() {
return BottomNavBarNoInkState();
}
}
class BottomNavBarNoInkState extends State<BottomNavBarNoInk> {
List<Widget> barItems = [];
@override
void initState() {
// TODO: implement initState
super.initState();
transfer2Widget();
}
//根据items建立对应的widget
transfer2Widget(){
for(int i=0; i< widget.items.length;i++){
barItems.add(GestureDetector(
onTap: (){
widget.onTap(i);
//更新model的值
model?.setIndex(i);
},
child: BottomNoInkBarItem(item: widget.items[i],index: i,),
));
}
}
//用于保存当前第几个item被点击
IndexModel model ;
@override
Widget build(BuildContext context) {
//经过provider 保存IndexModel,
//子widget能够共享这个model并根据内部数据的变动自动刷新
return ChangeNotifierProvider(
create: (ctx){
model = IndexModel(widget.currentIndex);
return model;
},
child:Container(
width: widget.width,
height: widget.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: barItems,
),
) ,
) ;
}
复制代码
这里咱们依然使用系统的BottomNavigationBarItem对item进行封装.git
建立一个IndexModel对状态进行保存github
代码以下bash
class IndexModel extends ChangeNotifier{
int selectIndex;
IndexModel(@required this.selectIndex);
get index => selectIndex;
setIndex(int index){
selectIndex = index;
notifyListeners();
}
}
复制代码
在子Widget(BottomNoInkBarItem)中咱们经过Consumer来获取到Provider管理的对象,而且根据这个对象的值来构造子widget,若是Provider的值变更,子widget也会同步刷新。ide
代码以下:ui
class BottomNoInkBarItem extends StatefulWidget{
int index;
BottomNavigationBarItem item;
BottomNoInkBarItem({this.item,this.index});
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return BottomNoInkBarItemState();
}
}
class BottomNoInkBarItemState extends State<BottomNoInkBarItem> {
@override
Widget build(BuildContext context) {
return Consumer<IndexModel>(
builder: (ctx,model,child){
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Stack(
children: <Widget>[
//未激活状态
Offstage(
offstage: model.index == widget.index,
child: widget.item.icon,
),
Offstage(
offstage: model.index != widget.index,
child: widget.item.activeIcon,
),
],
),
///title
widget.item.title
],
),
);
},
);
}
}
复制代码
至此功能就完成了,由于个人项目用到了Provider,因此这里便直接使用了。若是不想用Provider,也可使用stream来实现。 有其余骚操做的,请评论区告诉我,你们一块儿交流。this
Demo地址spa