效果:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pml2ZuIGM4kTYlRWOzUWM1IjZ4kjY0QDNjFmMkRDMyITZhRmZvwVN5MjMxgTOtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.gif)
像這種左右菜單關聯的效果很常見,即點選左邊菜單清單右邊重新整理,這裡示範一下在Flutter中的實作
頁面結構
很簡單,分為左右結構,左邊是一個ListView,右邊也是一個ListView,然後按比例顯示即可
return new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
flex: 2,
child: Container(
color: YColors.color_fff,
child: new ListView.builder(
itemCount: _datas.length,
itemBuilder: (BuildContext context, int position) {
return getRow(position);
}),
)),
new Expanded(
flex: 5,
child: ListView(
children: <Widget>[
Container(
//height: double.infinity,
alignment: Alignment.topLeft,
padding: const EdgeInsets.all(10),
color: YColors.color_f3f3f3,
child: getChip(index), //傳入一級分類下标
),
],
)),
],
);
複制
這裡用到
Expanded
,flex參數等同于Android中的權重。
然後把兩個ListView的item建構抽出來了。
左邊item getRow:
Widget getRow(int i) {
return new GestureDetector(
child: new Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10),
color: Colors.white,
child: new Text(_datas[i].name,
style: TextStyle( color: YColors.color_666, fontSize: 16)),
),
onTap: () {
setState(() {
});
},
);
}
複制
很簡單,就是一個text顯示文字。
右邊item getChip:
Widget getChip(int i) {
return Wrap(
spacing: 10.0, //兩個widget之間橫向的間隔
direction: Axis.horizontal, //方向
alignment: WrapAlignment.start, //内容排序方式
children: List<Widget>.generate(
articles.length,
(int index) {
return ActionChip(
//标簽文字
label: Text(articles[index].title,
style: TextStyle(fontSize: 16, color: YColors.color_666)),
//點選事件
onPressed: () {
},
elevation: 3,
);
},
).toList(),
);
}
複制
item用的是Chip标簽,Flutter Chip詳解
點選更新
ok ,現在是左右兩個清單都完成了(測試資料完全可以寫死),那怎麼做到點選左邊的item 重新整理右邊的清單呢?
在android 中可以用
notifyDataSetChanged
,在Flutter中,因為Widget 分為有狀态(
StatefulWidget
)和無狀态(
StatelessWidget
)的,是以要先繼承自
StatefulWidget
,然後用
setState
方法更新資料源即可。
是以我們單獨寫一個方法來更新資料:
List<NaviDataArticle> _updateArticles(int i) {
setState(() {
if (_datas.length != 0)
articles = _datas[i].articles;
});
return articles;
}
複制
接收一個int下标參數,根據一級分類下标更新二級分類集合。
一般進來都是預設選中第一個菜單,可以在
initState()
方法中對這個一級分類下标進行初始化,一級分類下标
index
預設為0
setState(() {
_datas = naviEntity.data;
index = 0;
});
複制
然後在一級分類清單的item點選事件中對一級分類index進行指派,并修改
選中item
的樣式。
Color textColor = YColors.colorPrimary; //字型顔色
Widget getRow(int i) {
return new GestureDetector(
child: new Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 10),
color: index == i ? YColors.color_f3f3f3 : Colors.white,
child: new Text(_datas[i].name,
style: TextStyle(
color: index == i ? textColor : YColors.color_666,
fontSize: 16)),
),
onTap: () {
setState(() {
index = i; //記錄選中的下标
textColor = YColors.colorPrimary;
});
},
);
}
複制
然後右邊清單在渲染之前,先更新資料
Widget getChip(int i) {
//更新對應下标資料
_updateArticles(i);
return Wrap(
...
);
}
複制
完整代碼:https://github.com/yechaoa/wanandroid_flutter/blob/master/lib/pages/naviPage.dart