先上效果图:
由于是学习中写下的,没有只选省市的功能,也没有在点击确定时做空判断,各位需要的拿走,下面是代码:
这个是选择界面代码:
import 'package:flutter/material.dart';
import 'package:hellowflutter/bean/AddressBean.dart';
import 'package:hellowflutter/utils/getTextStyle.dart';
/**
* create by wanghao
* 2019/9/9 14:32
**/
//typedef DataChangedCallback(String province, String city, String town);
//地址选择
class ChooseAddress {
static void showPicker(
BuildContext context, {
List<AddressBean> list,
bool showCountry: true,
Function onConfirm,
}) =>
Navigator.push(
context,
new _PickerRoute(
addressList: list,
showCountry: showCountry,
onConfirm: onConfirm,
// theme: Theme.of(context, shadowThemeOnly: true),
// barrierLabel:
// MaterialLocalizations.of(context).modalBarrierDismissLabel,
));
}
class _PickerRoute<T> extends PopupRoute<T> {
_PickerRoute({
this.addressList,
this.showCountry,
this.onConfirm,
this.theme,
this.barrierLabel,
RouteSettings settings,
}) : super(settings: settings);
final List<AddressBean> addressList;
final bool showCountry;
final Function onConfirm;
final ThemeData theme;
@override
Duration get transitionDuration => const Duration(milliseconds: 300);
@override
bool get barrierDismissible => true;
@override
final String barrierLabel;
@override
Color get barrierColor => null;
AnimationController _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController =
BottomSheet.createAnimationController(navigator.overlay);
return _animationController;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
Widget bottomSheet = new MediaQuery.removePadding(
context: context,
removeTop: false,
child: _ContentWidget(
route: this,
list: addressList,
showCountry: showCountry,
),
);
if (theme != null) {
bottomSheet = new Theme(data: theme, child: bottomSheet);
}
return _ContentWidget(
route: this,
list: addressList,
showCountry: showCountry,
);
}
}
class _ContentWidget extends StatefulWidget {
_ContentWidget({
Key key,
@required this.list,
@required this.route,
@required this.showCountry,
});
final _PickerRoute route;
List<AddressBean> list;
bool showCountry = true;
@override
State<StatefulWidget> createState() {
return _ContentState(showCountry, list);
}
}
class _ContentState extends State<_ContentWidget> {
bool showCountry;
List<AddressBean> list;
List<AddressBean> allList;
AddressBean provinceBean;
AddressBean cityBean;
AddressBean townBean;
String address="";
_ContentState(bool showCountry, List<AddressBean> list) {
if (list == null)
print("the list is null1");
else
print("the list is not null1");
allList = list;
if (provinceBean == null) {
this.list = allList;
} else {
if (cityBean == null) {
this.list = provinceBean.subList;
} else {
this.list = cityBean.subList;
}
}
}
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.black54,
child: Column(
children: <Widget>[
GestureDetector(
onTap: (){
Navigator.pop(context);
},
child: Container(
height: 200.0,
width: MediaQuery.of(context).size.width,
child: Text(""),
),
),
Container(
height: 50.0,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: Stack(
children: <Widget>[
Center(
child: Text("选择地址",style: getTextStyle("main_text"),),
),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: (){
if (widget.route.onConfirm != null) {
widget.route.onConfirm(
provinceBean.name, cityBean.name, townBean.name);
} else {
print("there is no onConfirm");
}
Navigator.pop(context);
},
child:Text(" 确定 ",style: getTextStyle("blue_text_normal"),),
),
),
],
),
),
Container(
height: 50.0,
width:MediaQuery.of(context).size.width ,
color:Colors.white,
child:Padding(
padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
child: Row(
children: <Widget>[
Expanded(
flex: 3,
child: Text(address,style: getTextStyle("main_text"),),
),
Expanded(
flex:1,
child: GestureDetector(
onTap: (){
if(townBean!=null){
townBean =null;
list = cityBean.subList;
} else {
if(cityBean!=null){
cityBean=null;
list = provinceBean.subList;
} else {
if(provinceBean!=null){
provinceBean = null;
list = allList;
}
}
}
address = getAddress();
setState(() {
});
},
child: Center(
child: Text("返回上一级",style: getTextStyle("blue_text_normal"),),
),
),
),
],
),
) ,
),
Container(
padding: EdgeInsets.fromLTRB(10, 0, 10, 10),
height: MediaQuery.of(context).size.height-300,
color: Colors.white,
child: GridView.builder(
gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent(
//SliverGridDelegateWithFixedCrossAxisCount可以直接指定每行(列)显示多少个Item
// SliverGridDelegateWithMaxCrossAxisExtent会根据GridView的宽度和你设置的每个的宽度来自动计算没行显示多少个Item
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
maxCrossAxisExtent: 150.0,
childAspectRatio: 5 / 2,
),
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
onTap: () {
if (list != null && list[index].subList.length > 0) {
if (provinceBean == null) {
provinceBean = list[index];
} else if (cityBean == null) {
cityBean = list[index];
}
if (cityBean == null) {
this.list = provinceBean.subList;
} else {
this.list = cityBean.subList;
}
} else {
townBean = list[index];
}
address = getAddress();
setState(() {
});
},
child: new ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Container(
padding: EdgeInsets.all(5.0),
color: Colors.blueGrey,
child: Center(
child: Text(
list[index].name,
style: getTextStyle("white_text_normal"),
textAlign: TextAlign.center,
),
),
),
),
);
},
itemCount: list.length,
),
),
],
),
);
}
String getAddress() {
String address="";
if(provinceBean!=null) {
address = provinceBean.name;
if(cityBean!=null){
address += " " + cityBean.name;
if(townBean!=null){
address += " " + townBean.name;
}
}
}
return address;
}
}
下面是使用代码:
ChooseAddress.showPicker(
context,
list: addressList,
showCountry: true,
onConfirm: (p, c, t) {
fromProvince = p;
fromCity = c;
fromTown = t;
setState(() {
});
},
);
省市县列表是从本地json文件里解析出来的,可以查看之前我的博客:flutter 解析本地json文件