Flutter 中的 ListView 组件和 RN 中的 ScrollView/FlatList 非常相似
ListView({
Axis scrollDirection = Axis.vertical,
ScrollController controller,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
double cacheExtent,
List<Widget> children = const <Widget>[],
})
- scrollDirection: 列表的滚动方向,可选值有Axis的horizontal和vertical,可以看到默认是垂直方向上滚动;
- controller : 控制器,与列表滚动相关,比如监听列表的滚动事件;
- physics: 列表滚动至边缘后继续拖动的物理效果,Android与iOS效果不同。Android会呈现出一个波纹状(对应ClampingScrollPhysics),而iOS上有一个回弹的弹性效果(对应BouncingScrollPhysics)。如果你想不同的平台上呈现各自的效果可以使用AlwaysScrollableScrollPhysics,它会根据不同平台自动选用各自的物理效果。如果你想禁用在边缘的拖动效果,那可以使用NeverScrollableScrollPhysics;
- shrinkWrap: 该属性将决定列表的长度是否仅包裹其内容的长度。当ListView嵌在一个无限长的容器组件中时,shrinkWrap必须为true,否则Flutter会给出警告;
- padding: 列表内边距;
- itemExtent: 子元素长度。当列表中的每一项长度是固定的情况下可以指定该值,有助于提高列表的性能(因为它可以帮助ListView在未实际渲染子元素之前就计算出每一项元素的位置);
- cacheExtent: 预渲染区域长度,ListView会在其可视区域的两边留一个cacheExtent长度的区域作为预渲染区域(对于ListView.build或ListView.separated构造函数创建的列表,不在可视区域和预渲染区域内的子元素不会被创建或会被销毁);
- children: 容纳子元素的组件数组。
class List extends StatelessWidget {
const List({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
ACard(data: creditCardData),
BCard(data: petCardData),
CCard(data: friendCircleData),
],
);
}
}
class List extends StatelessWidget {
const List({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Color(0xFFEFEFEF),
child: ListView.builder(
itemCount: accountList.length,
itemBuilder: (context, index) {
return AccountCard(data: accountList[index]);
},
),
);
}
}
class List extends StatelessWidget {
const List({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: friendListData.length,
itemBuilder: (context, index) {
return FriendCard(data: friendListData[index]);
},
separatorBuilder: (context, index) {
return Divider(
height: .5,
indent: 75,
color: Color(0xFFDDDDDD),
);
},
);
}
}
下拉刷新
RefreshIndicator的用法十分简单,只要将我们原来的ListView作为其child,并且实现其onRefresh方法就好了
return RefreshIndicator(
onRefresh: this.onRefresh,
child: ListView.separated(
itemCount: friendListData.length,
itemBuilder: (context, index) {
return FriendCard(data: friendListData[index]);
},
separatorBuilder: (context, index) {
return Divider(
height: .5,
indent: 75,
color: Color(0xFFDDDDDD),
);
},
),
);
上拉加载
import 'dart:async';
import 'package:flutter/material.dart';
class LoadMoreList extends StatefulWidget {
const LoadMoreList({Key key}) : super(key: key);
@override
_LoadMoreListState createState() => _LoadMoreListState();
}
class _LoadMoreListState extends State<LoadMoreList> {
bool loading = false;
ScrollController controller = ScrollController();
List<CardViewModel> list = List.from(cardList);
@override
void initState() {
super.initState();
// 给列表滚动添加监听
this.controller.addListener(() {
// 滑动到底部的关键判断
if (
!this.loading &&
this.controller.position.pixels >= this.controller.position.maxScrollExtent
) {
// 开始加载数据
setState(() {
this.loading = true;
this.loadMore();
});
}
});
}
@override
void dispose() {
// 释放资源,组件销毁时
this.controller.dispose();
super.dispose();
}
Future loadMore() {
return Future.delayed(const Duration(seconds: 1), () {
setState(() {
this.loading = false;
this.list.addAll(cardList);
});
});
}
@override
Widget build(BuildContext context) {
return ListView.separated(
controller: this.controller,
itemCount: this.list.length + 1,
separatorBuilder: (context, index) {
return Divider(height: .5, color: Color(0xFFEEEEEE));
},
itemBuilder: (context, index) {
if (index < this.list.length) {
return NewsCard(data: this.list[index]);
} else {
return this.genBottom();
}
},
);
}
Widget genBottom() {
if(this.loading) {
return Container(
padding: EdgeInsets.symmetric(vertical: 13.5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'加载中...',
style: TextStyle(
fontSize: 13.5,
color: Color(0xFF222222),
),
),
Padding(padding: EdgeInsets.only(left: 10)),
SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 3.5),
),
],
),
);
} else {
return Container(
padding: EdgeInsets.symmetric(vertical: 13.5),
alignment: Alignment.center,
child: Text(
'加载更多',
style: TextStyle(
fontSize: 13.5,
color: Color(0xFF222222),
),
),
);
}
}
}
class NewsCard extends StatelessWidget {
final CardViewModel data;
const NewsCard({Key key, this.data}) : super(key: key);
@override
Widget build(BuildContext context) {
// TODO: implement build
return null;
}
}
class CardViewModel {
}
const List<CardViewModel> cardList = [];