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