ListView 组件.png
- ListView: 可含多个子组件,支持按需加载。
- ScrollController: 用来控制可滚动组件的滚动位置。
- Scrollbar: 如果要给可滚动组件添加滚动条,只需 Scrollbar 作为其父组件即可。
- SingleChildScrollView: 只含单个子组件,建议内容超过屏幕不多时使用,因为它不支持基于Sliver按需加载模型。
常用组合布局
- Row [ Expanded (ListView) ]
- Column [ Expanded (ListView) ]
//导入Material UI 组件库
import 'package:flutter/material.dart';
//程序入口
void main() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false, home: ListViewWidget()));
}
class SingleChildScrollViewWidget extends StatelessWidget {
final String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const SingleChildScrollViewWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("SingleChildScrollView"),
),
//Scrollbar 显示滚动条
body: Scrollbar(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(16.0),
child: Center(
child: Row(
children: str
.split("")
.map((e) => Text(
e,
textScaleFactor: 2.0,
))
.toList()),
),
),
));
}
}
class ListViewWidget extends StatefulWidget {
const ListViewWidget({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _ListViewState();
}
class _ListViewState extends State<ListViewWidget> {
final List<List> _itemList = const [
["上海", "1 上海", Icon(Icons.keyboard)],
["天津", "2 天津", Icon(Icons.print)],
["北京", "3 北京", Icon(Icons.rocket)],
["内蒙", "4 内蒙", Icon(Icons.router)],
["黑龙江", "5 黑龙江", Icon(Icons.map)],
["江苏省", "6 江苏省", Icon(Icons.person)],
["浙江省", "7 浙江省", Icon(Icons.percent)],
["安徽省", "8 安徽省", Icon(Icons.add)],
["江西省", "9 江西省", Icon(Icons.abc)],
["山东省", "10 山东省", Icon(Icons.adjust)],
["香港", "11 香港", Icon(Icons.add_card)],
["澳门", "12 澳门", Icon(Icons.add_card)],
];
//是否显示"返回到顶部"按钮
bool showToTopBtn = false;
final List<Widget> _list = [];
final ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
for (int i = 0; i < _itemList.length; i++) {
_list.add(_buildListData(
context, _itemList[i][0], _itemList[i][2], _itemList[i][1]));
}
//监听滚动事件,打印滚动位置
_controller.addListener(() {
//打印滚动位置
print("offset: ${_controller.offset}");
if (_controller.offset < 400 && showToTopBtn) {
setState(() {
showToTopBtn = false;
});
} else if (_controller.offset >= 400 && showToTopBtn == false) {
setState(() {
showToTopBtn = true;
});
}
});
}
@override
void dispose() {
super.dispose();
//为了避免内存泄露,需要调用_controller.dispose
_controller.dispose();
}
Widget _buildListData(BuildContext context, String titleItem, Icon iconItem,
String subTitleItem) {
return ListTile(
leading: iconItem,
title: Text(
titleItem,
style: const TextStyle(fontSize: 18.0),
),
subtitle: Text(
subTitleItem,
),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
'ListViewAlert',
style: TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: Text('选择的item内容为: $titleItem'),
);
},
);
},
);
}
Widget _listView(List<Widget> _list) {
//需提前构建,适合较少数量已知数据
return ListView(
//item反向展示
reverse: true,
//滚动方向
scrollDirection: Axis.vertical,
//填充内边距
padding: const EdgeInsets.all(10.0),
//设置item高度
itemExtent: 100,
//设置预加载区域
cacheExtent: 100,
//是否根据item长度设置ListView的长度
shrinkWrap: false,
children: _list,
);
}
Widget _listViewBuilder() {
//适合列表项目较多或数量不确定时使用
return ListView.builder(
//设置item高度
itemExtent: 100,
controller: _controller,
itemBuilder: (context, index) {
// return _buildListData(context, _itemList[index][0], _itemList[index][2],
// _itemList[index][1]);
//包装后添加分割线
return Column(
children: [
_buildListData(context, _itemList[index][0], _itemList[index][2],
_itemList[index][1]),
//绘制分割线
const Divider(),
],
);
},
itemCount: _itemList.length,
);
}
Widget _listViewSeparated() {
//包含分割
return ListView.separated(
itemBuilder: (context, index) {
print("index: $index");
//返回 Widget
return _buildListData(context, _itemList[index][0], _itemList[index][2],
_itemList[index][1]);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider();
},
//必填参数
itemCount: _itemList.length,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ListView 组件'),
),
body: Scrollbar(
//child: _listView(_list),
child: _listViewBuilder(),
//child: _listViewSeparated(),
),
floatingActionButton: !showToTopBtn
? null
: FloatingActionButton(
child: const Icon(Icons.arrow_upward),
onPressed: () {
//跳转到顶部时执行动画
_controller.animateTo(
.0,
duration: const Duration(milliseconds: 200),
curve: Curves.ease,
);
}),
);
}
}