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.
 
 
 
 
 
 

370 lines
12 KiB

import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:huixiang/utils/font_weight.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import '../data/ip_data.dart';
import '../retrofit/retrofit_api.dart';
class UnionSelectCity extends StatefulWidget {
final Map<String, dynamic>? arguments;
UnionSelectCity({this.arguments});
@override
State<StatefulWidget> createState() {
return _UnionSelectCity();
}
}
class _UnionSelectCity extends State<UnionSelectCity> {
RefreshController refreshController = RefreshController();
late Map<String, dynamic> areaMap;
ApiService? apiIpService;
String? ipName;
int ipState = 0;
List<String> hotCity = [];
List<String> areaList = [];
@override
void initState() {
super.initState();
areaCode();
queryIpInfo();
}
void areaCode({String? searchTxt}) async {
var value =
await rootBundle.loadString('assets/map_style/chinese_cities.json');
areaList.clear();
areaMap = jsonDecode(value);
hotCity = (areaMap["热门城市"] as List).map((e) {
return e["area"].toString();
}).toList();
areaMap.remove("热门城市");
Map<String, dynamic> tempAreaMap = jsonDecode(value);
areaMap.forEach((key, value) {
if (searchTxt?.trim().isNotEmpty ?? false)
value.forEach((element) {
if (!element["area"].contains(searchTxt))
(tempAreaMap[key] as List)
.removeWhere((el) => el["area"] == element["area"]);
});
if (tempAreaMap[key].isNotEmpty) areaList.add(key);
});
areaMap = tempAreaMap;
setState(() {});
}
queryIpInfo() async {
apiIpService = ApiService(
Dio(),
context: context,
isIp: true
);
IpData? baseData = await apiIpService?.getIpInfo().catchError((onError) {});
ipName = baseData?.city?.replaceAll("", "");
if(ipName != widget.arguments?["cityName"] ){
ipState = 2;
setState((){});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Color(0xFFF0F0F0),
body: Container(
color: Color(0xFFF0F0F0),
child: Column(
children: [
Container(
color: Colors.white,
padding: EdgeInsets.only(left: 14.w, top: 44.h, bottom: 24.h),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(context).pop();
},
child: Container(
padding: EdgeInsets.only(right: 21.w),
child: Icon(
Icons.arrow_back_ios,
color: Colors.black,
),
)),
Expanded(child: searchCityItem())
],
),
Padding(
padding: EdgeInsets.only(top: 16.h, bottom: 24.h),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 10.w),
child: Text(
(ipState == 0||ipState == 1) ? "当前位置" : "已选:",
style: TextStyle(
color: Color(0xFFA29E9E),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
),
),
Image.asset(
"assets/image/icon_union_location.webp",
width: 20,
height: 20,
),
Expanded(
// padding: EdgeInsets.only(
// left: 8.w,
// ),
child: Text(
(ipState== 1) ? (ipName??"") : widget.arguments?["cityName"] ?? "",
style: TextStyle(
color: Color(0xFF4D4D4D),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
),
),
if(ipState == 2)
Icon(
Icons.gps_fixed,
color: Colors.grey,
size: 18,
),
if(ipState == 2)
Padding(padding:EdgeInsets.only(left:5.w,right: 12.w),
child:GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: (){
setState((){
ipState = 1;
Navigator.of(context).pop(ipName);
});
},
child: Text(
"重新定位",
style: TextStyle(
color: Color(0xFF4D4D4D),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
),
),)
],
)),
Padding(
padding: EdgeInsets.only(bottom: 16.h),
child: Text(
"热门城市",
style: TextStyle(
color: Color(0xFFA29E9E),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
),
),
GridView.builder(
itemCount: hotCity.length,
padding: EdgeInsets.only(right: 14.h, bottom: 14.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 12.w,
mainAxisSpacing: 12.w,
childAspectRatio: 2.5,
),
itemBuilder: (context, index) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(context).pop(hotCity[index]);
setState((){});
},
child: Container(
decoration: BoxDecoration(
color: Color(0xFFF7F7F7),
borderRadius: BorderRadius.circular(4),
),
alignment: Alignment.center,
child: Text(
hotCity[index],
style: TextStyle(
color: Color(0xFF4D4D4D),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
)));
},
),
],
),
),
Expanded(child: sortList())
],
),
),
);
}
Widget searchCityItem() {
return Container(
margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0),
padding: EdgeInsets.symmetric(vertical: 6.h),
decoration: BoxDecoration(
color: Color(0xFFF1F1F1),
borderRadius: BorderRadius.circular(6),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(12),
offset: Offset(0, 3),
blurRadius: 14,
spreadRadius: 0,
),
],
),
child: TextField(
textInputAction: TextInputAction.search,
onEditingComplete: () {
FocusScope.of(context).requestFocus(FocusNode());
},
onChanged: (txt) {
areaCode(searchTxt: txt);
},
style: TextStyle(
fontSize: 14.sp,
),
decoration: InputDecoration(
hintText: "搜索联盟会员店",
hintStyle: TextStyle(
fontSize: 12.sp,
color: Color(0xFFB3B3B3),
),
isCollapsed: true,
prefixIcon:Padding(padding: EdgeInsets.only(left: 5.w,right: 5.w),child: Image.asset(
"assets/image/icon_search.webp",
width: 16.h,
height: 16.h,
),),
prefixIconConstraints: BoxConstraints(),
border: InputBorder.none,
),
),
);
}
Widget sortList() {
return areaList.length != 0 ?ListView.builder(
padding: EdgeInsets.zero,
itemCount: areaList.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemBuilder: (context, position) {
return GestureDetector(
onTap: () {},
child: sortItem(position),
);
},
):Padding(padding:EdgeInsets.only(top:12.h),
child: Text(
// "抱歉,未找到相关位置,可尝试修改后重试",
"抱歉,该城市未开设门店,可尝试修改后重试",
style: TextStyle(
color: Color(0xFF4D4D4D),
fontWeight: MyFontWeight.medium,
fontSize: 14.sp,
),
));
}
Widget sortItem(int position) {
return Column(
children: [
Container(
width: double.infinity,
// color: Colors.white,
padding: EdgeInsets.only(top: 14.h, bottom: 4.h, left: 16.w),
margin: EdgeInsets.only(bottom: 12.h),
child: Text(
areaList[position],
style: TextStyle(
color: Color(0xFF4D4D4D),
fontWeight: MyFontWeight.medium,
fontSize: 16.sp,
),
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.w),
color: Colors.white,
),
margin: EdgeInsets.symmetric(horizontal: 14.w),
padding: EdgeInsets.only(
top: 8.h,
),
child: mapWidget(position),
)
],
);
}
Widget mapWidget(position) {
int mapIndex = 0;
return Column(
children: (areaMap[areaList[position]] as List).map((e) {
mapIndex += 1;
return globalRoamingItem(
e, mapIndex == areaMap[areaList[position]].length);
}).toList(),
);
}
Widget globalRoamingItem(data, isLast) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
Navigator.of(context).pop(data["area"]);
},
child: Container(
width: double.infinity,
child: Text(
data["area"],
style: TextStyle(
color: Color(0xFF000000),
fontWeight: MyFontWeight.regular,
fontSize: 14.sp,
),
),
decoration: BoxDecoration(
border: isLast
? null
: Border(
bottom: BorderSide(
width: 1.w,
color: Color(0xFFDCDCDC),
style: BorderStyle.solid,
),
),
),
padding: EdgeInsets.only(top: 16.h, bottom: 16.h, left: 16.w),
),
);
}
}