基于ListView實現(xiàn)水平和垂直方向滾動列表
實現(xiàn)垂直滾動列表
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
const CITY_NAMES = ['北京', '上海', '廣州', '深圳', '海南', '杭州', '蘇州', '溫州'];
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: Text('ListView'),),
body: ListView(
children: _buildList(),
),
),
);
}
List<Widget> _buildList() {
return CITY_NAMES.map((city) => _item(city)).toList();
}
Widget _item(String city) {
return Container(
height: 80,
margin: EdgeInsets.only(bottom: 5),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.teal),
child: Text(
city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
}
也可以使用ListView.Builder更加高效的實現(xiàn)列表(適用于動態(tài)列表或者數(shù)據(jù)來給你較大時)
home: Scaffold(
appBar: AppBar(title: Text('ListView'),),
body: ListView.builder(
itemCount: CITY_NAMES.length,
itemBuilder: (BuildContext context, int position) {
return _buildList()[position];
},
),
),
實現(xiàn)水平滾動列表
水平滾動只需要為ListView添加scrollDirection: Axis.horizontal參數(shù)即可
home: Scaffold(
appBar: AppBar(title: Text('ListView'),),
body: ListView(
scrollDirection: Axis.horizontal,
children: _buildList(),
),
),
- 為ListView設(shè)置高度需要對ListView外層Container設(shè)置高度
基于ExpansionTitle實現(xiàn)可展開的列表
ExpansionTitle基本知識
const ExpansionTile({
Key key,
this.leading,//標(biāo)題左側(cè)要展示的widget
@required this.title,//要展示的標(biāo)題widget(是整個標(biāo)題父控件)
this.backgroundColor,//背景
this.onExpansionChanged,//列表展開收起的回調(diào)函數(shù)
this.children = const <Widget>[],//列表展開時顯示的widget
this.trailing,//標(biāo)題右側(cè)要展示的widget
this.initiallyExpanded = false,//是否默認(rèn)狀態(tài)下展開
}) : assert(initiallyExpanded != null),
super(key: key);
-
數(shù)據(jù)要求
const CITY_NAMES = { '北京': ['東城區(qū)', '西城區(qū)', '豐臺區(qū)', '海淀區(qū)', '房山區(qū)'], '上海': ['黃埔區(qū)', '徐匯區(qū)', '虹口區(qū)'], '杭州': ['上城區(qū)', '下城區(qū)'] };
-
ExpansionTitle
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); const CITY_NAMES = { '北京': ['東城區(qū)', '西城區(qū)', '豐臺區(qū)', '海淀區(qū)', '房山區(qū)'], '上海': ['黃埔區(qū)', '徐匯區(qū)', '虹口區(qū)'], '杭州': ['上城區(qū)', '下城區(qū)'] }; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'ExpansionTile Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar(title: Text('ListView'),), body: ListView( children: _buildList(), ), ), ); } List<Widget> _buildList() { List<Widget> widgets = []; CITY_NAMES.keys.forEach((key) { widgets.add(_item(key, CITY_NAMES[key])); }); return widgets; } Widget _item(String city, List<String> subCities) { return ExpansionTile( title: Text( city, style: TextStyle(color: Colors.black54, fontSize: 20), ), children: subCities.map((subCities) => _buildSub(subCities)).toList(), ); } Widget _buildSub(String subCity) { return FractionallySizedBox(//可伸縮(如果不設(shè)置FractionallySizedBox臂拓,子列表寬度無法撐滿屏幕) widthFactor: 1, child: Container( height: 50, margin: EdgeInsets.only(bottom: 5), decoration: BoxDecoration(color: Colors.lightBlueAccent), child: Text(subCity), ), ); } }
基于GridView實現(xiàn)網(wǎng)格列表
GridView時flutter中用于展示網(wǎng)格布局風(fēng)格的widget,通常使用GridView.count構(gòu)造函數(shù)來創(chuàng)建一個GridView
與ListView用法一直,只需要使用GridView.count構(gòu)建即可
home: Scaffold(
appBar: AppBar(title: Text('ListView'),),
body: GridView.count(
crossAxisCount: 2,//列數(shù)
children: _buildList(),
),
),
高級功能列表下拉刷新與上拉加載更多
實現(xiàn)下拉刷新
使用RefreshIndicator實現(xiàn)列表的下拉刷新
實現(xiàn)上拉加載
借助ScrollController,為列表設(shè)置controller參數(shù),通過ScrollController監(jiān)聽列表滾動的位置,實現(xiàn)加載更多功能
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
List<String> cityNames = [
'北京', '上海', '廣州', '深圳', '海南', '杭州', '蘇州', '溫州', '泉州', '保定', '鄭州', '唐山', '東京'];
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ScrollController _scrollController = ScrollController();
@override
void initState() {
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) { //當(dāng)前位置等于可滾動位置
_loadData();
}
});
super.initState();
}
@override
void dispose() {
//在聲明周期結(jié)束的時候?qū)⒈O(jiān)聽移除
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '下拉刷新',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: Text('ListView'),),
body: RefreshIndicator(
child: ListView(
controller: _scrollController,
children: _buildList(),
),
onRefresh: _handleRefresh)
),
);
}
List<Widget> _buildList() {
return cityNames.map((city) => _item(city)).toList();
}
Widget _item(String city) {
return Container(
height: 80,
margin: EdgeInsets.only(bottom: 5),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.teal),
child: Text(
city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
Future<Null> _handleRefresh() async {
await Future.delayed(Duration(seconds: 2));
setState(() {
cityNames = cityNames.reversed.toList();
});
return null;
}
_loadData() async {
await Future.delayed(Duration(milliseconds: 200));
setState(() {
List<String> list = new List <String>.from(cityNames);
list.addAll(cityNames);
cityNames = list;
});
}
}