You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
9.4 KiB

/*
* ====================================================
* package :
* author : Created by nansi.
* time : 2019-07-17 09:41
* remark :
* ====================================================
*/
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter/material.dart';
import 'package:recook/constants/app_image_resources.dart';
import 'package:recook/constants/constants.dart';
import 'package:recook/constants/styles.dart';
import 'package:recook/models/province_city_model.dart';
import 'package:recook/utils/text_utils.dart';
import 'package:recook/widgets/custom_image_button.dart';
import 'custom_bottom_sheet.dart';
typedef AddressSelectorCallback = Function(
String province, String city, String disctrict);
class AddressSelector extends StatefulWidget {
final ProvinceCityModel model;
final String province;
final String city;
final String district;
final AddressSelectorCallback callback;
const AddressSelector(
{@required this.model,
this.province = "",
this.city = "",
this.district = "",
this.callback})
: assert(model != null),
assert(callback != null);
@override
_AddressSelectorState createState() => _AddressSelectorState();
}
class _AddressSelectorState extends State<AddressSelector>
with TickerProviderStateMixin {
ScrollController _scrollController;
TabController _tabController;
List<List<String>> _items;
List<String> _result;
List<int> _indexs;
Province _province;
City _city;
District _district;
Color _selectedColor = AppColor.themeColor;
BuildContext _context;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_items = [[], [], []];
_indexs = [null, null, null];
_result = [widget.province, widget.city, widget.district];
_filterAddress();
}
@override
Widget build(BuildContext context) {
_context = context;
return GestureDetector(
onTap: () {},
child: _buildBody(),
);
}
@override
void dispose() {
_scrollController?.dispose();
_tabController?.dispose();
super.dispose();
}
Container _buildBody() {
return Container(
height: (DeviceInfo.screenHeight * 0.75).rw,
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(10))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[_header(), _tabBar(), _list()],
),
);
}
Container _header() {
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Row(
children: <Widget>[
Text(
"配送至",
style: TextStyle(
fontSize: 18 * 2.sp,
fontWeight: FontWeight.w500,
color: Colors.black),
),
Spacer(),
CustomImageButton(
padding: EdgeInsets.all(5),
borderRadius: BorderRadius.all(Radius.circular(20)),
icon: Icon(
AppIcons.icon_delete,
color: Colors.grey[500],
size: 12,
),
backgroundColor: Colors.grey[200],
onPressed: () {
_dismiss();
},
)
],
),
);
}
TabBar _tabBar() {
return TabBar(
controller: _tabController,
labelPadding: EdgeInsets.zero,
unselectedLabelColor: Colors.black,
isScrollable: true,
indicatorColor: _selectedColor,
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.only(left: 10, right: 10),
tabs: _tabItems());
}
_tabItems() {
List<Widget> list = [];
// for (int i = 0; i < _items.length; ++i) {
for (int i = 0; i < _tabController.length; ++i) {
List addressModels = _items[i];
if (addressModels == null || addressModels.length == 0) {
list.add(Container());
continue;
}
list.add(Container(
margin: EdgeInsets.symmetric(horizontal: 5),
height: 30,
alignment: Alignment.center,
child: Text(
TextUtils.isEmpty(_result[i]) ? "请选择" : _result[i],
style: TextStyle(
fontSize: 16 * 2.sp,
color: _tabController.index == i ? _selectedColor : Colors.black),
),
));
}
return list;
}
Expanded _list() {
return Expanded(
child: ListView.builder(
controller: _scrollController,
itemCount: _items[_tabController.index].length,
itemBuilder: (context, index) {
String addr = _items[_tabController.index][index];
bool selected = addr == _result[_tabController.index];
return CustomImageButton(
padding: EdgeInsets.zero,
child: Container(
padding: EdgeInsets.symmetric(vertical: 6),
child: Row(children: [
Text(
addr,
style: TextStyle(
fontSize: 15 * 2.sp,
color: selected ? _selectedColor : Colors.black),
),
Spacer(),
Offstage(
offstage: !selected,
child: Icon(
Icons.check,
size: 16 * 2.sp,
))
]),
),
onPressed: () {
_itemSelected(index);
},
);
}),
);
}
void _filterAddress() {
int index = 1;
for (int i = 0; i < widget.model.data.length; ++i) {
Province province = widget.model.data[i];
String proAddressStr = province.name;
_items[0].add(proAddressStr);
if (proAddressStr != widget.province) {
continue;
}
_indexs[0] = i;
// index++;
_province = province;
for (int m = 0; m < province.cities.length; ++m) {
City city = province.cities[m];
String cityAddressStr = city.name;
_items[1].add(cityAddressStr);
if (cityAddressStr != widget.city) {
continue;
}
_city = city;
_indexs[1] = m;
index++;
for (int n = 0; n < city.districts.length; ++n) {
District district = city.districts[n];
String disAddressStr = district.name;
_items[2].add(disAddressStr);
if (disAddressStr != widget.district) {
continue;
}
_indexs[2] = n;
index++;
_district = district;
}
}
}
_resetTabBar(index);
}
void _resetTabBar(int index) {
_tabController?.removeListener(_tabBarListener);
_tabController = TabController(length: index, vsync: this);
_tabController.addListener(_tabBarListener);
_tabController.index = index - 1;
}
_itemSelected(int index) {
switch (_tabController.index) {
case 0:
{
/// 选城市
Province province = widget.model.data[index];
_items[1].clear();
_items[2].clear();
_province = province;
_result[0] = _province.name;
_result[1] = "";
_result[2] = "";
_indexs[0] = index;
_indexs[1] = null;
_indexs[2] = null;
_city = null;
/// 没有次级列表返回
if (_province.cities.length == 0) {
_dismiss();
widget.callback(_province.name, null, null);
return;
}
province.cities.forEach((City city) {
_items[1].add(city.name);
});
_resetTabBar(2);
_scrollController.jumpTo(0);
setState(() {});
}
break;
case 1:
{
/// 选城市
City city = _province.cities[index];
_city = city;
_district = null;
_items[2].clear();
_result[1] = _city.name;
_indexs[1] = index;
_result[2] = "";
_indexs[2] = null;
/// 没有次级列表返回
if (city.districts.length == 0) {
_dismiss();
widget.callback(_province.name, _city.name, null);
return;
}
city.districts.forEach((District district) {
_items[2].add(district.name);
});
_resetTabBar(3);
setState(() {});
_scrollController.jumpTo(0);
}
break;
case 2:
{
/// 选区
District district = _city.districts[index];
_district = district;
_result[2] = _district.name;
_indexs[2] = index;
_dismiss();
widget.callback(_province.name, _city.name, _district.name);
}
}
}
_tabBarListener() {
if (_scrollController.hasClients) {
_scrollController?.jumpTo(0);
setState(() {});
}
}
_dismiss() {
Navigator.maybePop(_context);
}
}
class AddressSelectorHelper {
static show(BuildContext context,
{@required ProvinceCityModel model,
String province,
String city,
String district,
AddressSelectorCallback callback}) {
showCustomModalBottomSheet(
context: context,
builder: (context) {
return AddressSelector(
model: model,
province: province,
city: city,
district: district,
callback: callback,
);
});
}
}