效果:

Flutter 左右菜单联动_Flutter左右列表Flutter 左右菜单联动_Expanded_02

像这种左右菜单联动的效果很常见,即点击左边菜单列表右边刷新,这里演示一下在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​