【Flutter 专题】14 图解 ListView 不同样式 item 及 Widget 显隐性
一年一度的谷歌大会又开始了,谷歌对 Flutter 的投入力度又加大了,所以更得好好学 Flutter 了。小菜在做新闻列表方面的 Demo 时,想到会在列表中展示多种不同 item 样式,今天特意借助上一篇关于 ListView 的小例子 稍微调整一下,测试 ListView 中多种 item 样式展示方式。
尝试如下
小菜按照 Android 的想法,应该会对 Android 列表的 ViewHolder 中进行状态判断;类似的小菜想在 itemBuilder 中对布局样式进行判断,想法是可以的,只是在实践中遇到两个小小的问题,分析一下,如下:
Widget buildListData(
BuildContext context, String strItem, Icon iconItem, int type) {
Widget widget;
switch (type) {
case 1:
...
break;
case 2:
...
break;
}
return widget;
}
实践注意
一. item 类型显示不完整
- 小菜首先往 buildListData 中传入 item 样式类型,针对样式类型判断 Widget 样式,当然类型传入方式多种多样按实际情况而定;
List<int> stateItems = <int>[
1, 1, 2, 2, 0, 1, 1, 1, 0, 1, 2, 2, 1, 2,
];
-
小菜编辑了一个 stateItems 有 0,1,2 三种样式类型,但是在 buildListData 中只判断了 1 和 2 两种,小菜以为会隐藏掉当前 item,可结果出乎意料,在 0 及以后的 item 全部不显示,完全中断;如图:
-
添加相应的判断处理之后即正常展示,如图:
二. GestureDetector 手势方法注意
默认很多 Widget 没有 onTab() 方法,但是可以用 GestureDetector 来进行手势处理;小菜建议使用 GestureDetector 时针对具体的 Widget,例如对 item 进行点击操作时,对整个 item 外添加 GestureDetector,小菜当时糊涂把 GestureDetector 添加错 Widget 以为使用方式有问题,请各位注意。
三. Widget 显隐性
小菜在实际测试的过程中需要用到【Widget 显隐性】,小菜想 Flutter 最大的特点就是一切都是 Widget,同时 Widget 不可为 null(错误:Widget wi = null),于是小菜把需要隐藏的 Widget 设置宽和高为 0.0,当然这是很蠢的方法,随着对 Flutter 的了解,可以用 Offstage,通过设置 offstage 熟悉来处理显隐性,true 为隐藏,false 为显示。
Widget wi;
if ('图标 -> pages' == strItem) {
wi = new Container(height: 0.0, width: 0.0);
} else {
wi = new Text(
strItem,
style: new TextStyle(color: Colors.blueAccent, fontSize: 18.0),
);
}
// Offstage 方式
Offstage(
offstage: ('图标 -> pages' == strItem) ? true : false,
child: Text(strItem, style: TextStyle(color: Colors.blueAccent, fontSize: 18.0))),
核心源码
List<int> stateItems = <int>[
1, 1, 2, 2, 0, 1, 1, 1, 0, 1, 2, 2, 1, 2,
];
List<String> strItems = <String>[
'图标 -> keyboard', '图标 -> print', '图标 -> router',
'图标 -> pages', '图标 -> zoom_out_map', '图标 -> zoom_out',
'图标 -> youtube_searched_for', '图标 -> wifi_tethering', '图标 -> wifi_lock',
'图标 -> widgets', '图标 -> weekend', '图标 -> web', '图标 -> accessible', '图标 -> ac_unit',
];
List<Icon> iconItems = <Icon>[
new Icon(Icons.keyboard), new Icon(Icons.print), new Icon(Icons.router),
new Icon(Icons.pages), new Icon(Icons.zoom_out_map), new Icon(Icons.zoom_out),
new Icon(Icons.youtube_searched_for), new Icon(Icons.wifi_tethering), new Icon(Icons.wifi_lock),
new Icon(Icons.widgets), new Icon(Icons.weekend), new Icon(Icons.web),
new Icon(Icons.accessible), new Icon(Icons.ac_unit),
];
Widget buildListData(
BuildContext context, String strItem, Icon iconItem, int type) {
Widget widget;
switch (type) {
case 1:
widget = new ListTile(
isThreeLine: false,
leading: iconItem,
title: new Text(strItem),
trailing: new Icon(Icons.keyboard_arrow_right),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: new Text(
'ListViewDemo',
style: new TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: new Text('您选择的item内容为:$strItem,item 状态为 1'),
);
},
);
},
);
break;
case 2:
Widget wi;
if ('图标 -> pages' == strItem) {
wi = new Container(height: 0.0, width: 0.0);
} else {
wi = new Text(
strItem,
style: new TextStyle(color: Colors.blueAccent, fontSize: 18.0),
);
}
widget = new GestureDetector(
child: new Column(
children: <Widget>[
iconItem,
wi,
],
),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: new Text(
'ListViewDemo',
style: new TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: new Text('您选择的item内容为:$strItem,item 状态为 2'),
);
},
);
},
);
break;
default:
widget = new Container(
height: 50.0,
color: Colors.greenAccent,
child: new Padding(
padding: new EdgeInsets.all(12.0),
child: new GestureDetector(
child: new Text('我是状态为0的item'),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: new Text(
'ListViewDemo',
style: new TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: new Text('哈哈哈!当前 item 状态为 0'),
);
},
);
},
),
),
);
break;
}
return widget;
}
小菜刚接触 Flutter 时间不长,还有很多不清楚和不理解的地方,如果又不对的地方还希望多多指出!
来源:阿策小和尚
- 点赞
- 收藏
- 关注作者
评论(0)