目录
- 从零开始写第一个Flutter app(一)——Hello World
- 从零开始写第一个Flutter app(二)——引用第三方包
- 从零开始写第一个Flutter app(三)——有状态的部件StatefulWidget
- 从零开始写第一个Flutter app(四)——无限滑动的ListView
- 从零开始写第一个Flutter app(五)——ListView添加图标
- 从零开始写第一个Flutter app(六)——添加点击事件交互
- 从零开始写第一个Flutter app(七)——弹出toast
- 从零开始写第一个Flutter app(八)——修改主题颜色
- 从零开始写第一个Flutter app(九)——route跳转新页面
- 从零开始写第一个Flutter app(十)——最终代码
本节目标
ListView是开发中比较常用到的控件,本节课的目标是实现一个无线滑动的ListView,每当滑到底部时会自动生成10条数据,这样永远也滑不完
完整实现代码
由于本节代码相比前面几节的代码稍多点,所以先贴代码加注释,可以先看代码知道个大致的实现,然后后面再讲解一些疑点难点,不会说直接讲代码片段会有点不知所云,有点懵逼
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
home: RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => new RandomWordsState();
}
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[]; // ListView用的数据源
final _biggerFont = const TextStyle(fontSize: 18.0); // 字体大小
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
),
body: _buildSuggestions(), // body为一个ListView
);
}
Widget _buildSuggestions() {
return ListView.builder(
padding: const EdgeInsets.all(16.0), // 设置padding
itemBuilder: (context, i) {
if (i.isOdd) return Divider(); // 如果为基数,返回分割线
final index = i ~/ 2; // 由于divider也占一个位置,所以需除以2计算实际的index
// 若数据源不够,则一次性生成10条数据,这样就可以实现ListView无限滑动的效果
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
// 生成每一条item布局
return _buildRow(_suggestions[index]);
});
}
// 创建ListView的Item
Widget _buildRow(WordPair pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
}
}
代码解析
- RandomWordsState改成返回Scaffold,Scaffold的body内容是由方法_buildSuggestions()返回的ListView
- ListView由ListView.builder()类生成,里面的itemBuilder属性设置Item
- 需注意,这里的分割线也算item,按顺序0、2、4、6等偶数位置是实际的item,1、3、5、7等奇数位置是分割线
- if (i.isOdd) return Divider();判断如果是奇数就返回分割线
- final index = i ~/ 2;是为了计算扣除分割线后实际的item的位置,比如0、1、2、3、4、5除以2后结果为0、0、1、1、2、2,在根据计算结果index从_suggestions里获取显示的内容
-
index >= _suggestions.length判断数据是否不够,若不够则通过generateWordPairs().take(10)生成10条数据添加到_suggestions中
-
_buildRow(WordPair pair)根据传入的WordPair返回一个ListTile控件,控件里面实际是一个Text控件,显示WordPair的内容。
运行结果