如果想去掉widget默认的padding,需要用MediaQuery.removePadding包裹
MediaQuery.removePadding(context: context,
removeTop: true,
child:widget)
基于ExpansionTile实现可展开的列表,相等于Android中的ExpandableListView
class SearchPage extends StatefulWidget{
@override
State<StatefulWidget> createState() => _SearchState();
}
class _SearchState extends State<SearchPage>{
var map = {
"北京":["东城区","西城区","朝阳区","海淀区","丰台区"],
"上海":["浦东区","虹口区","静安寺区"],
"山东":["济南","青岛","潍坊","烟台","聊城"]
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("搜索"),),
body: ListView(
children: _buildCity()
)
);
}
List<Widget> _buildCity(){
List<Widget> widgets = [];
map.keys.forEach((key){
widgets.add(_buildSubCity(map[key],key));
});
return widgets;
}
Widget _buildSubCity(List<String> subCities,String city){
return ExpansionTile(
title: Text(city),
initiallyExpanded:false,
children: subCities.map((title)=>_buildItem(title)).toList()
);
}
Widget _buildItem(String title){
return FractionallySizedBox(
widthFactor: 1,
child: Container(
height: 50,
alignment: Alignment.centerLeft,
child: Text(title),
color: Colors.lightBlue,
margin: EdgeInsets.only(top: 5),
),
);
}
}
基于GridView实现网格列表
class TravelPage extends StatefulWidget{
@override
State<StatefulWidget> createState() => _TravelState();
}
const CITY_NAMES = ['北京','上海','广州','深圳','杭州','苏州','天津','重庆','青岛','烟台','大连','哈尔滨'];
class _TravelState extends State<TravelPage>{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("旅拍"),),
body: GridView.count(
crossAxisCount: 2,
children: _buildItems(),
)
);
}
List<Widget> _buildItems(){
List<Widget> widgets = [];
for(int i = 0 ; i < CITY_NAMES.length; i++){
widgets.add(_buildItem(CITY_NAMES[i],i));
}
return widgets;
}
Widget _buildItem(String city,int position){
return Container(
height: 80,
decoration: BoxDecoration(color: Colors.teal),
margin: EdgeInsets.only(bottom: 5, right: position % 2 == 0 ? 2.5 : 0,left: position % 2 == 0 ? 0 : 2.5),
alignment: Alignment.center,
child: Text(city,
style: TextStyle(color: Colors.white,fontSize: 20),
),
);
}
}
高级功能列表下拉刷新和上拉加载更多功能的实现
下拉刷新的实现
1.使用RefreshIndicator包裹ListView
2.实现RefreshIndicator的onRefresh方法
上拉加载更多的实现:
1.为ListView设置一个ScrollController
2.为ScrollController在initState方法中添加一个监听:ScrollController.addListener((){});
3.在addListener中判断是否滑动到最下方(ScrollController.positon.pixels == ScrollController.position.maxScrollExtent)如果为true就执行loadMore方法
class MyPage extends StatefulWidget{
@override
State<StatefulWidget> createState() => _MyState();
}
const CITIES = ['北京','上海','广州','深圳','杭州','苏州','天津','重庆','青岛','烟台','大连','哈尔滨','洛阳','无锡'];
class _MyState extends State<MyPage>{
var cities = List<String>.from(CITIES);
var _scrollController = ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener((){
print(_scrollController.position);
print(_scrollController.position.pixels);
if(_scrollController.position.pixels == _scrollController.position.maxScrollExtent){
_onLoadMore();
print("on load more");
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
Future<Null> _onLoadMore() async{
await Future.delayed(Duration(milliseconds: 500));
setState(() {
cities.add("load more");
});
return null;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("我的"),),
body: RefreshIndicator(child: ListView(
controller: _scrollController,
children: _buildItems(),
), onRefresh: _onRefresh)
);
}
List<Widget> _buildItems(){
return cities.map((city)=>_buildItem(city)).toList();
}
Widget _buildItem(String city) {
return Container(
height: 40,
decoration: BoxDecoration(color: Colors.teal),
margin: EdgeInsets.only(bottom: 5,),
alignment: Alignment.center,
child: Text(city,
style: TextStyle(color: Colors.white, fontSize: 20),
),
);
}
Future<Null> _onRefresh() async{
await Future.delayed(Duration(milliseconds: 2000));
setState(() {
cities = cities.reversed.toList();
});
return null;
}
}