1.jpg
2.jpg
3.jpg
樣式如圖
貼代碼
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/common/Constant.dart';
import 'package:flutter_app/common/http/Api.dart';
import 'package:flutter_app/common/http/ApiUrl.dart';
import 'package:flutter_app/model/user_center/HHSRegion.dart';
import 'package:flutter_app/model/user_center/LocalQueryBean.dart';
///地址選擇器
class SelectAddressWidget extends StatefulWidget {
SelectAddressWidget({Key key, @required this.valueCb}) :super(key: key);
///回調(diào)函數(shù)
final Function valueCb;
@override
_SelectAddressWidgetState createState() => new _SelectAddressWidgetState();
}
class _SelectAddressWidgetState extends State<SelectAddressWidget>
with SingleTickerProviderStateMixin {
///區(qū)域信息列表
List<HHSRegion> localList;
///TabBarController
TabController _tabController;
///選擇的省市縣的名字
String selectProvinceStr = '省份';
String selectCityStr = '城市';
String selectDistrictStr = '區(qū)/縣';
///選擇的省市縣Id
int selectProvinceId = -1;
int selectCityId = -1;
int selectDistrictId = -1;
///當(dāng)前Tab位置
int currentTabPos = 0;
Map<String, int> selectMap = new Map();
///Tab Text樣式
TextStyle tabTvStyle = new TextStyle(
color: Colors.black, fontSize: 18.0, fontWeight: FontWeight.w300);
@override
void initState() {
// TODO: implement initState
super.initState();
///給區(qū)域Id Map一個初始值
selectMap['selectProvinceId'] = -1;
selectMap['selectCityId'] = -1;
selectMap['selectDistrictId'] = -1;
///初始化控制器
_tabController = new TabController(length: 3, vsync: this);
_tabController.addListener(() {
///獲取tab當(dāng)前點(diǎn)擊位置
currentTabPos = _tabController.index;
///切換Tab重新請求列表數(shù)據(jù)
if (_checkTabCanSelect(currentTabPos)) {
_queryLocal(currentTabPos == 0 ? 1 : currentTabPos == 1
? selectProvinceId
: selectCityId);
}
print(currentTabPos);
});
///第一次進(jìn)來 這里調(diào)用我自己的接口 查詢?nèi)珖乃惺?可以替換成其他
_queryLocal(1);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
///去掉左箭頭
automaticallyImplyLeading: false,
title: new Text(
'配送至', style: new TextStyle(color: const Color(0xff666666)),),
centerTitle: true,
elevation: 0.5,
backgroundColor: Colors.white,
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.close, color: const Color(0xff666666),),
onPressed: () => Navigator.pop(context))
],
),
body: _getBody(),
);
}
///構(gòu)建底部視圖
Widget _getBody() {
if (_showLoadingDialog()) {
return new Center(child: new CircularProgressIndicator(),);
} else {
return _buildContent();
}
}
///根據(jù)數(shù)據(jù)是否有返回顯示加載條或者列表
bool _showLoadingDialog() {
if (localList == null || localList.length == 0) {
return true;
} else {
return false;
}
}
///有數(shù)據(jù)時構(gòu)建tab和區(qū)域列表
Widget _buildContent() {
return new Container(
child: new Column(
children: <Widget>[
new Padding(padding: const EdgeInsets.only(top: 18.0)),
new TabBar(
indicatorColor: Colors.black,
controller: _tabController,
tabs: <Widget>[
new Text('$selectProvinceStr', style: tabTvStyle, maxLines: 1,),
new Text('$selectCityStr', style: tabTvStyle, maxLines: 1,),
new Text('$selectDistrictStr', style: tabTvStyle, maxLines: 1,),
],
),
new Padding(padding: const EdgeInsets.only(top: 18.0)),
_buildListView(),
],
),
color: Colors.white,
);
}
///構(gòu)建列表
Widget _buildListView() {
return new Expanded(
child: new ListView.builder(
shrinkWrap: true,
itemCount: localList.length,
itemBuilder: (BuildContext context, int position) {
return _buildListRow(position);
},
)
);
}
///構(gòu)建子項(xiàng)
Widget _buildListRow(int position) {
return new ListTile(
title: new Text('${localList[position].regionName}',
style: new TextStyle(color: const Color(0xff666666), fontSize: 15.0),),
onTap: () => _onLocalSelect(position),);
}
///區(qū)域位置選擇
_onLocalSelect(int position) {
_setSelectData(position);
if (currentTabPos != 2) {
_queryLocal(localList[position].regionId);
}
}
///設(shè)置選擇的數(shù)據(jù)
///根據(jù)當(dāng)前選擇的列表項(xiàng)的position 和 Tab的currentTabPos
///@params position 當(dāng)前列表選擇的省或市或縣的position
_setSelectData(position) {
if (currentTabPos == 0) {
selectProvinceId = localList[position].regionId;
selectProvinceStr = localList[position].regionName;
selectMap['provinceId'] = selectProvinceId;
setState(() {
selectCityStr = '城市';
selectDistrictStr = '區(qū)/縣';
});
selectCityId = -1;
selectDistrictId = -1;
}
if (currentTabPos == 1) {
selectCityId = localList[position].regionId;
selectCityStr = localList[position].regionName;
selectMap['selectCityId'] = selectCityId;
setState(() {
selectDistrictStr = '區(qū)/縣';
});
selectDistrictId = -1;
}
if (currentTabPos == 2) {
selectDistrictId = localList[position].regionId;
selectDistrictStr = localList[position].regionName;
selectMap['selectDistrictId'] = selectDistrictId;
///拼接區(qū)域字符串 回調(diào)給上個頁面 關(guān)閉彈窗
String localStr = selectProvinceStr + ' ' + selectCityStr + ' ' +
selectDistrictStr;
widget.valueCb(selectMap, localStr);
Navigator.pop(context);
}
currentTabPos++;
_tabController.animateTo(currentTabPos);
}
///檢查是否可以選擇下級Tab
bool _checkTabCanSelect(int position) {
if (position == 0) {
return true;
}
if (position == 1) {
if (selectProvinceId == -1) {
_tabController.animateTo(0);
_showSnack();
return false;
}
return true;
}
if (position == 2) {
if (selectProvinceId == -1 && selectCityId == -1) {
_tabController.animateTo(0);
_showSnack();
return false;
}
if (selectProvinceId != -1 && selectCityId == -1) {
_tabController.animateTo(1);
_showSnack();
return false;
}
return true;
}
}
///顯示錯誤信息
_showSnack() {
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text('請先選擇上級地區(qū)')));
}
///查詢區(qū)域信息
_queryLocal(int parentId) {
String url = Constant.HOST + ApiUrl.LOCAL_QUERY;
Map<String, dynamic> params = new Map();
params['parentId'] = parentId;
Api.post(url, (Response response) {
LocalQueryBean localQueryBean = LocalQueryBean.fromJSON(response.data);
///這里防止沒有區(qū)的城市查詢不到還不會關(guān)閉對話框回調(diào)到地址頁面 例如三亞市
///寫的有點(diǎn)亂
if (currentTabPos == 2 && localQueryBean.regionList == null) {
String localStr = selectProvinceStr + ' ' + selectCityStr;
widget.valueCb(selectMap, localStr);
Navigator.pop(context);
}
setState(() {
localList = localQueryBean.regionList;
});
},
errorCallBack: (errMsg) {
},
params: params);
}
@override
void dispose() {
// TODO: implement dispose
_tabController.dispose();
super.dispose();
}
}
HHSRegion類
import 'package:json_annotation/json_annotation.dart';
part 'HHSRegion.g.dart';
@JsonSerializable()
class HHSRegion {
int regionId; // 當(dāng)前區(qū)域ID
int parentId; // 當(dāng)前區(qū)域父ID
String regionName; // 區(qū)域名字
int regionType; // 區(qū)域類型(0:國;1:省;2:市;3:區(qū))
int agencyId;
HHSRegion(this.regionId, this.parentId, this.regionName, this.regionType,
this.agencyId); // 不知道是啥
//反序列化
factory HHSRegion.fromJson(Map<String, dynamic> json)=>
_$HHSRegionFromJson(json);
//序列化
Map<String, dynamic> toJson() => _$HHSRegionToJson(this);
}
需要將 _queryLocal(int parentId)這個方法替換成你自己的請求地址列表 或者加載本地JSON
做的不完善 而且靈活度非常低 對于選擇地址應(yīng)該夠了 再變態(tài)也改不到哪去了
使用方法
///顯示選擇所在地址彈窗
_showSelectAddrDialog() {
///顯示一個BottomSheet
showModalBottomSheet(
context: context,
///_handleLocal是被回調(diào)頁面的方法 用于接收選擇的地址
builder: (context) => new SelectAddressWidget(valueCb: _handleLocal,),
);
}