目标:
1)Flutter有哪些常用的列表组建
2)怎么定制列表项Item?
一、ListView简介
使用标准的 ListView 构造方法非常适合只有少量数据的列表。我们还将使用内置的 ListTile widget 来给我们的条目提供可视化结构。ListView支持横向列表和纵向列表。
ListTile相当于列表项 Item,可以定制列表项内容。
例如:可以在ListView的属性children中定义 ListTile组件列表。
ListView(
children: const <Widget>[
ListTile(
leading: Icon(Icons.map),
title: Text('Map'),
),
ListTile(
leading: Icon(Icons.photo_album),
title: Text('Album'),
),
ListTile(
leading: Icon(Icons.phone),
title: Text('Phone'),
),
],
),
1.1 ListView属性
padding属性
padding定义控件内边距
padding: EdgeInsets.all(8.0),
children属性
children属性是定义列表项Item,是一个ListTile列表。
scrollDirection属性
ListView列表滚动方向。包括:
Axis.vertical: 竖直方向滚动,对应的是纵向列表。
Axis.horizontal: 水平方向滚动,对应的是横向列表。
1.2 ListTile组件
常用的ListView项,包含图标,Title,文本,按钮等。
class ListTile extends StatelessWidget {
ListTile是StatelessWidget,常用的一些属性:
leading属性
标题Title之前Widget,通常是 Icon或者圆形图像CircleAvatar 组件。
ListTile(
leading: Icon(Icons.photo_album), // 标题图片
title: Text('Album'),
),
title属性
列表Item标题。
titleTextStyle属性
标题文本样式
titleAlignment属性
标题文本的对齐属性
subtitle属性
subtitle 副标题,显示位置位于标题之下。
ListTile(
leading: Icon(Icons.photo_album), // 标题图片
title: Text('Album'),
subtitle: Text('手机历史相册'),
),
subtitleTextStyle属性
副标题文本样式
isThreeLine属性
布尔值,指示是否为三行列表项。如果为 true
,则可以显示额外的文本行。否则,只有一行文本。
dense属性
是否是紧凑布局。布尔型,紧凑模式下,文本和图标的大小将减小。
textColor属性
文本颜色
contentPadding属性
内容区的内边距
enabled属性
布尔值,指示列表项是否可用。如果为 false
,则列表项将不可点击。
selected属性
布尔值,指示列表项是否已选择。列表选择时有效
focusColor属性
获取焦点时的背景颜色。
hoverColor属性
鼠标悬停时的背景颜色。
splashColor属性
点击列表项时的水波纹颜色。
tileColor属性
列表项的背景颜色
selectedTileColor属性
选中列表项时的背景颜色。
leadingAndTrailingTextStyle属性
前导和尾部部分文本的样式。
enableFeedback属性
是否启用触觉反馈。
horizontalTitleGap属性
标题与前导/尾部之间的水平间距。
minVerticalPadding属性
最小垂直内边距
minLeadingWidth属性
最小前导宽度
二、定制ListView的子项Item
ListView可以展现简单的列表。如果子项包括有状态更新,和原来一样,可以在State中进行状态更新。
2.1 竖直列表
对应的代码
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: ListView(
children: [
const ListTile(
leading: Icon(Icons.map), // 标题图片
title: Text('Map'),
),
ListTile(
leading: Icon(Icons.photo_album), // 标题图片
title: Text('Album'),
),
ListTile(
leading: Icon(Icons.photo_camera), // 标题图片
title: Text('Camera'),
),
ListTile(
leading: Icon(Icons.countertops), // 标题图片
title: Text(
'当前计数$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
2.2 水平列表
ListView设置显示水平布局,增加属性 scrollDirection: Axis.horizontal, 则显示水平列表。
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
const title = 'Horizontal List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: const Text(title),
),
body: Container(
margin: const EdgeInsets.symmetric(vertical: 20),
height: 200,
child: ListView(
// This next line does the trick.
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160,
color: Colors.red,
),
Container(
width: 160,
color: Colors.blue,
),
Container(
width: 160,
color: Colors.green,
),
Container(
width: 160,
color: Colors.yellow,
),
Container(
width: 160,
color: Colors.orange,
),
],
),
),
),
);
}
}