Flutter 中我们可以通过 ListView 来定义列表项,支持垂直和水平方向展示。通过一个属性就可以控制列表的显示方向。列表有一下
分类:
1、垂直列表
2、垂直图文列表
3、水平列表
4、动态列表
5、矩阵式列表
名称 | 类型 | 说明 |
---|---|---|
scrollDirection | Axis | Axis.horizontal 水平列 Axis.vertical 垂直列表(默认) |
padding | EdgeInsetsGeometry | 内边距 |
resolve | bool | 组件反向排序 |
children | List< Widget> | 列表元素 |
对于ListTile组件我的理解是相当于我们以前Java Android时列表中的单个条目,不过Flutter已经帮我们封装好了,条目中有以下几个常用属性
this.leading, //放在条目前面(左边)的图片
this.title, //条目的主标题
this.subtitle, //条目的副标题
this.trailing, //放在条目后面(右边)的图片
children: < Widget>[ …]中返回的的是一个组件集合,里面包含多个组件,每个子组件就相当于我们列表中的一个条目,常与ListTile组件结合显示类似新闻列表
// ignore_for_file: non_constant_identifier_names, prefer_const_constructors
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: const HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
padding:EdgeInsets.all(10),
children: <Widget>[
ListTile(
leading: Icon(Icons.ac_unit,size: 30,),
title: Text("解决github下载速度慢问题"),
subtitle: Text("我们需要从github拉取一套代码到我们本地,我们国内下载速度非常慢,现在分享一种解决方案提高下载速度。"),
),
ListTile(
leading: Image.asset("images/a.jpg",),
title: Text("final属性值能被反射修改吗?"),
subtitle: Text("有网友询问反射给final修饰的字段设值,为啥设值会失败,之前也深入学习一下反射。"),
),
ListTile(
leading: Icon(Icons.access_time_filled,color: Colors.yellow,),
title: Text("当Jetpack Compose遇到Navigation"),
subtitle: Text("Jetpack Compose作为一个声明式UI框架经常拿来与React 、Flutter等作对比"),
),
ListTile(
title: Text("Android Canvas画布解析"),
subtitle: Text("在开发中,我们经常需要自定义View去实现各种各样的效果,经常需要用到Canvas画布去绘制各种各样的图形和图案"),
trailing: Icon(Icons.access_time_sharp),
),
],
);
}
}
注意:下边例子中我们在listview外部又加了一个Container,原因是当我们设置方向为水平时,条目中高度属性会失效,默认为对齐父组件,因此我们在listview外部又加了一个Container,然后指定高度,这样listview高度就被限制。同样的在垂直方向时listview内部条目默认宽度于父布局一致,设置宽度无效
这里listview里面用的是container组件展示每个条目
// ignore_for_file: non_constant_identifier_names, prefer_const_constructors
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: const HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 200.0,
margin: EdgeInsets.all(5),
child: ListView(
//设置列表为水平列表
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 180.0,
color: Colors.lightBlue,
),
Container(
width: 180.0,
color: Colors.amber,
child: ListView(
children: <Widget>[
Image.network(
'https://cdn.stocksnap.io/img-thumbs/960w/flower-bouquet_X6UBKGVU0Z.jpg'),
SizedBox(height: 16.0),
Text(
'这是一个文本信息',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0),
)
],
)),
Container(
width: 180.0,
color: Colors.deepOrange,
),
Container(
width: 180.0,
color: Colors.deepPurpleAccent,
),
],
));
}
}
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: const HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
//自定义方法
List<Widget> _getData() {
List<Widget> list = [];
for (var i = 0; i < 20; i++) {
list.add(ListTile(
title: Text("我是第$i个条目"),
));
}
return list;
}
@override
Widget build(BuildContext context) {
return ListView(
children: _getData(),
);
}
}
List listData=[
{
"title": 'Candy Shop',
"author": 'Mohamed Chahin',
"imageUrl": 'https://www.itying.com/images/flutter/1.png',
},
{
"title": 'Childhood in a picture',
"author": 'Google',
"imageUrl": 'https://www.itying.com/images/flutter/2.png',
},
{
"title": 'Alibaba Shop',
"author": 'Alibaba',
"imageUrl": 'https://www.itying.com/images/flutter/3.png',
},
{
"title": 'Candy Shop',
"author": 'Mohamed Chahin',
"imageUrl": 'https://www.itying.com/images/flutter/4.png',
},
{
"title": 'Tornado',
"author": 'Mohamed Chahin',
"imageUrl": 'https://www.itying.com/images/flutter/5.png',
},
{
"title": 'Undo',
"author": 'Mohamed Chahin',
"imageUrl": 'https://www.itying.com/images/flutter/6.png',
},
{
"title": 'white-dragon',
"author": 'Mohamed Chahin',
"imageUrl": 'https://www.itying.com/images/flutter/7.png',
}
];
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: const HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
//自定义方法
List<Widget> _getData() {
var list = <Widget>[];
/*
遍历外部listData获取数据生成listtile集合的两种方法
*/
//第一种
var tempList = listData.map((e) {
return ListTile(
leading: Image.network(e["imageUrl"]),
title: Text(e["title"]),
subtitle: Text(e["author"]),
);
});
//第二种
for (int i = 0; i < listData.length; i++) {
list.add(ListTile(
leading: Image.network(listData[i]["imageUrl"]),
title: Text(listData[i]["title"]),
subtitle: Text(listData[i]["author"]),
));
}
return list;
// return tempList.toList();
}
@override
Widget build(BuildContext context) {
return ListView(
children: _getData(),
);
}
}
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable, must_be_immutable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
List list = [];
HomeContent({Key? key}) : super(key: key) {
for (var i = 0; i < 20; i++) {
list.add("我是第$i个条目");
}
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(list[index]),
);
});
}
}
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable, must_be_immutable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
Widget _getListData(context, index) {
return ListTile(
leading: Image.network(listData[index]["imageUrl"]),
title: Text(listData[index]["title"]),
subtitle: Text(listData[index]["author"]),
);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: listData.length,
//注意这里是赋值不是调用方法,因此不加()
itemBuilder: _getListData
);
}
}
当数据量很大的时候用矩阵方式排列比较清晰。此时我们可以用网格列表组
件 GridView 实现布局。
GridView 创建网格列表有多种方式,下面我们主要介绍两种。
名称 | 类型 | 说明 |
---|---|---|
scrollDirection | Axis | 滚动方法 |
padding | EdgeInsetsGeometry | 内边距 |
resolve | bool | 组件反向排序 |
crossAxisSpacing | double | 水平子 Widget 之间间距 |
mainAxisSpacing | double | 垂直子 Widget 之间间距 |
crossAxisCount | int | 一行的 Widget 数量 |
childAspectRatio | double | 子 Widget 宽高比例 |
children | < Widget>[ ] | |
gridDelegate | (常用)SliverGridDelegateWithFixedCrossAxisCount SliverGridDelegateWithMaxCrossAxisExtent |
控制布局主要用在GridView.builder 里面 |
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable, must_be_immutable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
List<Widget> _getListData() {
List<Widget> list = [];
for (var i = 0; i < 20; i++) {
list.add(Container(
alignment: Alignment.center,
child: Text(
"这是第$i个条目",
style: TextStyle(color: Colors.white, fontSize: 20),
),
color: Colors.blue,
height: 500,
));
}
return list;
}
@override
Widget build(BuildContext context) {
return GridView.count(
//水平子元素之间的距离
crossAxisSpacing: 20,
//垂直子元素之间的距离
mainAxisSpacing: 20,
padding: EdgeInsets.all(10),
crossAxisCount: 3,
//内部设置单个条目宽高无效,可以改变宽高比例达到目的,
childAspectRatio: 0.7,
children: _getListData());
}
}
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable, must_be_immutable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
List<Widget> _getListData() {
var tempList = listData.map((value) {
return Container(
child: Column(
children: <Widget>[
Image.network(value["imageUrl"]),
SizedBox(height: 12),
Text(value["title"],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20)
),
],
),
decoration: BoxDecoration(
border: Border.all(
color: Color.fromRGBO(230, 230, 230, 0.9),
width: 1.0),
borderRadius: const BorderRadius.all(
Radius.circular(15),
)
),
);
});
return tempList.toList();
}
@override
Widget build(BuildContext context) {
return GridView.count(
padding: EdgeInsets.all(20),
crossAxisCount: 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
childAspectRatio: 0.7,
children: _getListData());
}
}
// ignore_for_file: prefer_const_constructors, prefer_collection_literals, deprecated_member_use, unused_local_variable, must_be_immutable
import 'package:flutter/material.dart';
import 'res/listData.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: HomeContent(),
),
theme: ThemeData(
primarySwatch: Colors.yellow,
),
);
}
}
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
Widget _getListData(context, index) {
return Container(
child: Column(
children: <Widget>[
Image.network(listData[index]["imageUrl"]),
SizedBox(height: 12),
Text(listData[index]["title"],
textAlign: TextAlign.center, style: TextStyle(fontSize: 20)),
],
),
decoration: BoxDecoration(
border: Border.all(
color: Color.fromRGBO(230, 230, 230, 0.9), width: 1.0)),
);
}
@override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: listData.length,
itemBuilder: _getListData,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
//横轴元素个数
crossAxisCount: 2, //纵轴间距
mainAxisSpacing: 20.0, //横轴间距
crossAxisSpacing: 10.0, //子组件宽高长度比例
childAspectRatio: 1.0),
);
}
}