上面的代码是仿照慕课网上的实战案列学习的代码,如若有侵权的地方,请及时通知我关闭
ListView的世界
在下是一个垂直分布滚动的案列:
import 'package:flutter/material.dart';
class ListViewPage extends StatelessWidget {
//城市列表数组
static const CITY_NAMES = [
'北京',
'上海',
'广州',
'深圳',
'杭州',
'苏州',
'成都',
'武汉',
'郑州',
'长沙',
'云南',
'长春',
'黑龙江'
];
final String title = "Basic List";
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
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: 10),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.teal),
child: Text(city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
}
效果如图:
水瓶布局:
import 'package:flutter/material.dart';
class ListViewPage extends StatelessWidget {
//城市列表数组
static const CITY_NAMES = [
'北京',
'上海',
'广州',
'深圳',
'杭州',
'苏州',
'成都',
'武汉',
'郑州',
'长沙',
'云南',
'长春',
'黑龙江'
];
final String title = "Basic List";
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
height: 120,
child: ListView(
scrollDirection: Axis.horizontal,
children: _buildList(),
),
)
),
);
}
List<Widget> _buildList() {
return CITY_NAMES.map((city) => _item(city)).toList();
}
Widget _item(String city) {
return Container(
height: 80,
width: 80,
margin: EdgeInsets.only(bottom: 10,right: 20),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.teal),
child: Text(
city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
}
相对于垂直布局其实代码上没做多大的改动,水平布局中改变item的高度需设置外层widget的高度,不然会铺满全屏。
效果如图:
ExpansionTile实现列表的展开与收起
详细代码如下:
import 'package:flutter/material.dart';
//下啦展开案例
class ExpansionTitlePage extends StatelessWidget {
static const CITY_NAMES = {
'北京': ['朝阳区', '东城区', '西城区', '丰台区', '海淀区', '顺义区'],
'上海': ['黄浦区', '徐汇区', '闵行区', '松江区', '青浦区', '普陀区', '嘉定区', '闸北区', '静安区'],
'广州': ['海珠区', '越秀区', '荔湾区', '天河区', '白云区', '黄埔区', '南沙区', '番禺区'],
'深圳': ['南山区', '福田区', '宝安区', '盐田区', '龙岗区', '罗湖区', '龙华区', '光明区'],
'杭州': ['上城区', '下城区', '江干区', '拱墅区', '西湖区', '滨江区'],
'苏州': ['姑苏区', '吴中区', '相城区', '高新区', '虎丘区', '工业园区', '吴江区'],
};
final title = '列表的展开与收起';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
child: 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.red, fontSize: 20),
),
children: subCities.map((subCity) => _buildSubCities(subCity)).toList(),
);
}
Widget _buildSubCities(String subCity) {
return FractionallySizedBox(
widthFactor: 1,
child: Container(
height: 50,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 20),
margin: EdgeInsets.only(bottom: 5),
decoration: BoxDecoration(color: Colors.blueGrey),
child: Text(subCity,style: TextStyle(color: Colors.white,fontSize: 15),),
),
);
}
}
FractionallySizedBox
组建实现了item的铺满效果,widthFactor
类似布局权限的。
GridView的世界
根据买的教程,我先了解下利用GridView.count()
来实现网格布局。
import 'package:flutter/material.dart';
//网格布局
class GridViewPage extends StatelessWidget {
final String title;
GridViewPage(this.title);
//城市列表数组
static const CITY_NAMES = [
'北京',
'上海',
'广州',
'深圳',
'杭州',
'苏州',
'成都',
'武汉',
'郑州',
'长沙',
'云南',
'长春',
'黑龙江'
];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(
title,
style: TextStyle(color: Colors.blueGrey),
),
backgroundColor: Colors.green,
),
body: GridView.count(
crossAxisCount: 3,
children: _getGridListView(),
),
),
);
}
List<Widget> _getGridListView() {
return CITY_NAMES.map((city) => _GridItemView(city)).toList();
}
Widget _GridItemView(String city) {
return Container(
height: 80,
margin: EdgeInsets.only(bottom: 5),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.orange),
child: Text(
city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
}
实现的效果运行如下图:
实现下拉刷新
首先Widget
要继承StatefulWidget
,因为是带状态的。
利用重要的组件RefreshIndicator
实现下拉刷新的监听。编写刷新的状态onRefresh: _handleRefresh,
import 'package:flutter/material.dart';
//下拉刷新
class ListViewRefreshPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ListViewRefreshPageState();
}
}
class _ListViewRefreshPageState extends State<ListViewRefreshPage> {
final String title = "下拉刷新";
//城市列表数组
List<String> CITY_NAMES = [
'北京',
'上海',
'广州',
'深圳',
'杭州',
'苏州',
'成都',
'武汉',
'郑州',
'长沙',
'云南',
'长春',
'黑龙江'
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: RefreshIndicator(
child: new ListView(
children: _buildList(),
),
onRefresh: _handleRefresh,
),
);
}
Future<Null> _handleRefresh() async {
//延迟两秒
await Future.delayed(Duration(seconds: 2));
setState(() {
CITY_NAMES = CITY_NAMES.reversed.toList();
});
}
//执行刷新
List<Widget> _buildList() {
return CITY_NAMES.map((city) => _item(city)).toList();
}
Widget _item(String city) {
return Container(
height: 80,
margin: EdgeInsets.only(bottom: 10),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.teal),
child: Text(
city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
}
实现效果为:
实现加载更多
利用ScrollController
监听界面的上下滑动实现_loadData()
方法:
ScrollController _scrollController = ScrollController();
@override
void initState() {
_scrollController.addListener(() {
if (_scrollController.position.pixels
== _scrollController.position.maxScrollExtent){
//上拉加载更多
_loadData();
}
});
super.initState();
}
_loadData()是自定义的一个获取更多数据的方法
void _loadData() async{
//延时2秒,模拟网络请求
await Future.delayed(Duration(seconds: 2));
setState(() {
List<String> list = List<String>.from(CITY_NAMES);
list.addAll(CITY_NAMES);
CITY_NAMES = list;
});
}
重点是要利用好这个_scrollController;
body: RefreshIndicator(
child: new ListView(
children: _buildList(),
controller: _scrollController,
),
onRefresh: _handleRefresh,
),
最后千万别忘记去除_scrollController
滚动监听,不然容易造成不别要的资源浪费,具体什么浪费在这就不做详述啦!百度上有文章介绍。
@override
void dispose() {
//移除滑动监听
_scrollController.dispose();
super.dispose();
}
总结
巧用Container来设置每个Item布局的样式,代码的地址在自己的码云上。