Flutter滚动型容器组件 - ListView篇 · Issue #13 · SmallStoneSK/Blog · GitHub
source link: https://github.com/SmallStoneSK/Blog/issues/13?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Comments
无论是为了技术尝鲜还是以后可能的工作机会,都9102年了,作为一个前端开发者,似乎没有理由不去尝试它。正是带着这样的心理,笔者也开始学习 在上一篇文章中,我们学习了 2. ListView使用方法从功能比较上来看, 2.1 ListView()第一种使用方法就是直接调用其 不过话说回来,虽然该方法可能会有性能问题,但还是取决于其不同的应用场景而定。下面我们就来看下其构造函数(已省略不常用属性): ListView({ Axis scrollDirection = Axis.vertical, ScrollController controller, ScrollPhysics physics, bool shrinkWrap = false, EdgeInsetsGeometry padding, this.itemExtent, double cacheExtent, List<Widget> children = const <Widget>[], })
上面的属性介绍一大堆,都不如一个实际例子来得实在。我们可以用一个 代码(文件地址) class NormalList extends StatelessWidget { const NormalList({Key key}) : super(key: key); @override Widget build(BuildContext context) { return ListView( children: <Widget>[ CreditCard(data: creditCardData), PetCard(data: petCardData), FriendCircle(data: friendCircleData), ], ); } } 预览 可以看到, 2.2 ListView.build()
ListView.builder({ ... int itemCount, @required IndexedWidgetBuilder itemBuilder, }) 这里省略了不常用以及和
不同于 代码(文件地址) class SubscribeAccountList extends StatelessWidget { const SubscribeAccountList({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Container( color: Color(0xFFEFEFEF), child: ListView.builder( itemCount: subscribeAccountList.length, itemBuilder: (context, index) { return SubscribeAccountCard(data: subscribeAccountList[index]); }, ), ); } } 预览 根据上面的代码可以看到, 2.3 ListView.separated()绝大多数列表类的需求我们都可以用 ListView.separated({ ... @required IndexedWidgetBuilder separatorBuilder }) 相比于 代码(文件地址) class FriendList extends StatelessWidget { const FriendList({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), ); }, ); } } 预览 看代码可以知道不同点就在于实现了 2.4 小结到目前为止,我们一共学习了 不过,其实 3. ListView进阶方法上文我们介绍了 3.1 下拉刷新要在 class PullDownRefreshList extends StatefulWidget { const PullDownRefreshList({Key key}) : super(key: key); @override _PullDownRefreshListState createState() => _PullDownRefreshListState(); } class _PullDownRefreshListState extends State<PullDownRefreshList> { Future onRefresh() { return Future.delayed(Duration(seconds: 1), () { Toast.show('当前已是最新数据', context); }); } @override Widget build(BuildContext context) { 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), ); }, ), ); } } 由于列表的数据源是可变的,因此这次的组件我们选用继承自 可以看到 这里模仿了今日头条的列表UI作为示例(新闻卡片的样式布局可以看这里),我们来看下效果: 可以看到一切都如预期成功执行了,效果还是不错的,而且 3.2 上拉加载除了下拉刷新之外,上拉加载是经常会遇到的另一种列表操作。不过,这次
根据上面的思路,我们可以得到下面的代码: class PullUpLoadMoreList extends StatefulWidget { const PullUpLoadMoreList({Key key}) : super(key: key); @override _PullUpLoadMoreListState createState() => _PullUpLoadMoreListState(); } class _PullUpLoadMoreListState extends State<PullUpLoadMoreList> { bool isLoading = false; ScrollController scrollController = ScrollController(); List<NewsViewModel> list = List.from(newsList); @override void initState() { super.initState(); // 给列表滚动添加监听 this.scrollController.addListener(() { // 滑动到底部的关键判断 if ( !this.isLoading && this.scrollController.position.pixels >= this.scrollController.position.maxScrollExtent ) { // 开始加载数据 setState(() { this.isLoading = true; this.loadMoreData(); }); } }); } @override void dispose() { // 组件销毁时,释放资源(一定不能忘,否则可能会引起内存泄露) super.dispose(); this.scrollController.dispose(); } Future loadMoreData() { return Future.delayed(Duration(seconds: 1), () { setState(() { this.isLoading = false; this.list.addAll(newsList); }); }); } Widget renderBottom() { // TODO } @override Widget build(BuildContext context) { return ListView.separated( controller: this.scrollController, itemCount: this.list.length + 1, separatorBuilder: (context, index) { return Divider(height: .5, color: Color(0xFFDDDDDD)); }, itemBuilder: (context, index) { if (index < this.list.length) { return NewsCard(data: this.list[index]); } else { return this.renderBottom(); } }, ); } } 其中有一点需要注意,列表的 Widget renderBottom() { if(this.isLoading) { return Container( padding: EdgeInsets.symmetric(vertical: 15), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( '努力加载中...', style: TextStyle( fontSize: 15, color: Color(0xFF333333), ), ), Padding(padding: EdgeInsets.only(left: 10)), SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 3), ), ], ), ); } else { return Container( padding: EdgeInsets.symmetric(vertical: 15), alignment: Alignment.center, child: Text( '上拉加载更多', style: TextStyle( fontSize: 15, color: Color(0xFF333333), ), ), ); } } 最后,我们再来看下最终的实现效果: 首先,本文介绍了常用的 通过文中的5个实际例子,相信你一定已经对 本文所有代码托管在这儿,欢迎一起交流学习~ |
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK