|
|
|
import 'dart:ui';
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/gestures.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
import 'package:flutter_baidu_mapapi_utils/flutter_baidu_mapapi_utils.dart';
|
|
|
|
import 'package:flutter_bmflocation/flutter_bmflocation.dart';
|
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
|
|
import 'package:huixiang/generated/l10n.dart';
|
|
|
|
import 'package:huixiang/main.dart';
|
|
|
|
import 'package:huixiang/retrofit/data/ip_data.dart';
|
|
|
|
import 'package:huixiang/retrofit/retrofit_api.dart';
|
|
|
|
import 'package:huixiang/union/union_list.dart';
|
|
|
|
import 'package:huixiang/utils/event_type.dart';
|
|
|
|
import 'package:huixiang/utils/location.dart';
|
|
|
|
import 'package:huixiang/view_widget/my_tab.dart';
|
|
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
|
import 'package:flutter_baidu_mapapi_base/flutter_baidu_mapapi_base.dart';
|
|
|
|
import 'package:visibility_detector/visibility_detector.dart';
|
|
|
|
|
|
|
|
import '../view_widget/location_tips.dart';
|
|
|
|
import '../view_widget/no_data_view.dart';
|
|
|
|
|
|
|
|
class UnionPage extends StatefulWidget {
|
|
|
|
final int initialIndex;
|
|
|
|
|
|
|
|
UnionPage(Key key, this.initialIndex) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<StatefulWidget> createState() {
|
|
|
|
return UnionPageState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class UnionPageState extends State<UnionPage>
|
|
|
|
with
|
|
|
|
AutomaticKeepAliveClientMixin,
|
|
|
|
WidgetsBindingObserver,
|
|
|
|
SingleTickerProviderStateMixin {
|
|
|
|
final TextEditingController editingController = TextEditingController();
|
|
|
|
bool isKeyBoardShow = false;
|
|
|
|
TabController tabController;
|
|
|
|
BMFCoordinate latLng;
|
|
|
|
String areaName;
|
|
|
|
List<GlobalKey> _allKey = [];
|
|
|
|
bool _isShowLocalTips = false;
|
|
|
|
double visiblePercentage;
|
|
|
|
|
|
|
|
jumpIndex(jpIndex) {
|
|
|
|
tabController.index = jpIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
super.dispose();
|
|
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
|
|
if (Location.getInstance() != null &&
|
|
|
|
Location.getInstance().aMapFlutterLocation != null)
|
|
|
|
Location.getInstance().aMapFlutterLocation.stopLocation();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
|
|
if (state == AppLifecycleState.resumed) {
|
|
|
|
// 处理应用程序切换回前台的逻辑
|
|
|
|
if(visiblePercentage == 1)
|
|
|
|
permissionSettings();
|
|
|
|
} else if (state == AppLifecycleState.paused) {
|
|
|
|
// 处理应用程序切换到后台的逻辑
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void permissionSettings() async {
|
|
|
|
if (_isShowLocalTips && await Permission.location.isGranted){
|
|
|
|
_isShowLocalTips = false;
|
|
|
|
getLocation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void didChangeMetrics() {
|
|
|
|
super.didChangeMetrics();
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
setState(() {
|
|
|
|
print("object: ${MediaQuery.of(context).viewInsets.bottom}");
|
|
|
|
if (MediaQuery.of(context).viewInsets.bottom == 0) {
|
|
|
|
if (isKeyBoardShow) {
|
|
|
|
isKeyBoardShow = false;
|
|
|
|
//关闭键盘 软键盘关闭了, 清除输入控件的焦点, 否则重新进入页面会导致软键盘再弹出问题
|
|
|
|
FocusScope.of(context).requestFocus(FocusNode());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
isKeyBoardShow = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
tabController = TabController(
|
|
|
|
length: 4, vsync: this, initialIndex: widget.initialIndex);
|
|
|
|
WidgetsBinding.instance.addObserver(this);
|
|
|
|
eventBus.on<EventType>().listen((event) {
|
|
|
|
if (event.type < 3) {
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
queryIpInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
getLocation({bool showLoading = true}) async {
|
|
|
|
if(showLoading)
|
|
|
|
EasyLoading.show(
|
|
|
|
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black);
|
|
|
|
bool powerFlag = false;
|
|
|
|
// bool finallyFlag = false;
|
|
|
|
try {
|
|
|
|
Future.delayed(Duration(seconds: 5), () {
|
|
|
|
// if (!finallyFlag)
|
|
|
|
Location.getInstance().stopLocation();
|
|
|
|
});
|
|
|
|
powerFlag = await Location.getInstance().startLocation(context,
|
|
|
|
(BaiduLocation result) async {
|
|
|
|
if (result != null &&
|
|
|
|
result.latitude != null &&
|
|
|
|
result.longitude != null) {
|
|
|
|
print("location: $result");
|
|
|
|
latLng = BMFCoordinate(result.latitude, result.longitude);
|
|
|
|
latLng = await BMFCalculateUtils.coordConvert(
|
|
|
|
coordinate: latLng,
|
|
|
|
fromType: BMF_COORD_TYPE.BD09LL,
|
|
|
|
toType: BMF_COORD_TYPE.COMMON);
|
|
|
|
await saveLatLng(
|
|
|
|
latLng, result.province, result.city, result.district);
|
|
|
|
print("union: Location result ${latLng.latitude} "
|
|
|
|
"${latLng.longitude}");
|
|
|
|
Location.getInstance().stopLocation();
|
|
|
|
} else {
|
|
|
|
await getLatLng();
|
|
|
|
}
|
|
|
|
loadFinish(showLoading: false);
|
|
|
|
});
|
|
|
|
} finally {
|
|
|
|
// finallyFlag = true;
|
|
|
|
if (!powerFlag) {
|
|
|
|
if (await Permission.locationWhenInUse.status.isGranted) {
|
|
|
|
getLocation();
|
|
|
|
} else {
|
|
|
|
_isShowLocalTips = true;
|
|
|
|
loadFinish(showLoading: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
saveLatLng(BMFCoordinate latLng, province, city, district) async {
|
|
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
|
|
await prefs.setString("latitude", "${latLng.latitude}");
|
|
|
|
await prefs.setString("longitude", "${latLng.longitude}");
|
|
|
|
if (province != null) await prefs.setString("province", province);
|
|
|
|
if (city != null) await prefs.setString("city", city);
|
|
|
|
if (district != null) await prefs.setString("district", district);
|
|
|
|
}
|
|
|
|
|
|
|
|
getLatLng() async {
|
|
|
|
var tempLatLng = await SharedPreferences.getInstance();
|
|
|
|
if (tempLatLng.containsKey("latitude") &&
|
|
|
|
tempLatLng.containsKey("longitude") &&
|
|
|
|
tempLatLng.containsKey("province") &&
|
|
|
|
tempLatLng.containsKey("city") &&
|
|
|
|
tempLatLng.containsKey("district")) {
|
|
|
|
latLng = BMFCoordinate(double.tryParse(tempLatLng.getString("latitude")),
|
|
|
|
double.tryParse(tempLatLng.getString("longitude")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
queryIpInfo() async {
|
|
|
|
EasyLoading.show(
|
|
|
|
status: S.current.zhengzaijiazai, maskType: EasyLoadingMaskType.black);
|
|
|
|
try {
|
|
|
|
ApiService apiIpService = ApiService(Dio(), context: context, isIp: true);
|
|
|
|
IpData baseData = await apiIpService.getIpInfo().catchError((onError) {});
|
|
|
|
if (baseData?.city != null) {
|
|
|
|
areaName = baseData.city.replaceAll("市", "");
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
getLocation(showLoading: false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loadFinish({bool showLoading = true}) {
|
|
|
|
if (showLoading)
|
|
|
|
EasyLoading.show(
|
|
|
|
status: S.current.zhengzaijiazai,
|
|
|
|
maskType: EasyLoadingMaskType.black);
|
|
|
|
_allKey = [GlobalKey(), GlobalKey(), GlobalKey(), GlobalKey()];
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
super.build(context);
|
|
|
|
return VisibilityDetector(
|
|
|
|
key: Key('my-widget-key'),
|
|
|
|
onVisibilityChanged: (visibilityInfo) {
|
|
|
|
visiblePercentage = visibilityInfo.visibleFraction;
|
|
|
|
if(visiblePercentage == 1)
|
|
|
|
permissionSettings();
|
|
|
|
},
|
|
|
|
child: GestureDetector(
|
|
|
|
behavior: HitTestBehavior.translucent,
|
|
|
|
onTap: () {
|
|
|
|
FocusScope.of(context).requestFocus(FocusNode());
|
|
|
|
},
|
|
|
|
child: Stack(
|
|
|
|
alignment: Alignment.bottomCenter,
|
|
|
|
children: [
|
|
|
|
Container(
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.only(left: 18.w, right: 10.w),
|
|
|
|
child: GestureDetector(
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
onTap: () {
|
|
|
|
Navigator.of(context).pushNamed(
|
|
|
|
'/router/union_select_city',
|
|
|
|
arguments: {"cityName": areaName}).then((value) {
|
|
|
|
if (value != null) {
|
|
|
|
areaName = value;
|
|
|
|
loadFinish();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
areaName ?? "",
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
maxLines: 1,
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 14.sp,
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
color: Colors.white),
|
|
|
|
),
|
|
|
|
Icon(
|
|
|
|
Icons.keyboard_arrow_down,
|
|
|
|
color: Colors.white,
|
|
|
|
size: 24,
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Expanded(child: buildSearchItem())
|
|
|
|
],
|
|
|
|
),
|
|
|
|
Align(
|
|
|
|
alignment: Alignment.centerLeft,
|
|
|
|
child: TabBar(
|
|
|
|
controller: tabController,
|
|
|
|
isScrollable: true,
|
|
|
|
//可滚动
|
|
|
|
indicatorColor: Colors.white,
|
|
|
|
labelColor: Colors.white,
|
|
|
|
labelStyle: TextStyle(
|
|
|
|
fontSize: 18.sp,
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
),
|
|
|
|
unselectedLabelStyle: TextStyle(
|
|
|
|
fontSize: 15.sp,
|
|
|
|
fontWeight: FontWeight.normal,
|
|
|
|
),
|
|
|
|
//未选中文字颜色
|
|
|
|
unselectedLabelColor: Colors.white,
|
|
|
|
indicatorSize: TabBarIndicatorSize.label,
|
|
|
|
//指示器与文字等宽
|
|
|
|
tabs: <Widget>[
|
|
|
|
MyTab(text: S.of(context).quanbu),
|
|
|
|
MyTab(text: S.of(context).chi),
|
|
|
|
MyTab(text: S.of(context).he),
|
|
|
|
MyTab(text: S.of(context).wan),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
_allKey.isEmpty
|
|
|
|
? NoDataView(
|
|
|
|
src: "assets/image/di_zhi.webp",
|
|
|
|
isShowBtn: false,
|
|
|
|
text: "暂无店铺列表~",
|
|
|
|
fontSize: 16.sp,
|
|
|
|
margin: EdgeInsets.only(top: 120.h),
|
|
|
|
)
|
|
|
|
: Expanded(
|
|
|
|
child: TabBarView(
|
|
|
|
controller: tabController,
|
|
|
|
children: [
|
|
|
|
UnionList(_allKey[0], "", latLng,
|
|
|
|
editingController.text, areaName),
|
|
|
|
UnionList(_allKey[1], "EATSTORE", latLng,
|
|
|
|
editingController.text, areaName),
|
|
|
|
UnionList(_allKey[2], "DRINKSTORE", latLng,
|
|
|
|
editingController.text, areaName),
|
|
|
|
UnionList(_allKey[3], "HAPPYSTORE", latLng,
|
|
|
|
editingController.text, areaName),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
padding:
|
|
|
|
EdgeInsets.only(top: MediaQuery.of(context).padding.top + 17.h),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
gradient: LinearGradient(
|
|
|
|
begin: Alignment.topCenter,
|
|
|
|
end: Alignment.bottomCenter,
|
|
|
|
colors: [
|
|
|
|
Color(0xFF32A060),
|
|
|
|
Color(0xFF32A060),
|
|
|
|
Colors.white,
|
|
|
|
Colors.white,
|
|
|
|
],
|
|
|
|
stops: [
|
|
|
|
0,
|
|
|
|
0.2,
|
|
|
|
0.4,
|
|
|
|
1
|
|
|
|
]),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
if (_isShowLocalTips)
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.only(bottom: 70.h),
|
|
|
|
child: LocationTips(() {
|
|
|
|
setState(() {
|
|
|
|
_isShowLocalTips = false;
|
|
|
|
});
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget buildSearchItem() {
|
|
|
|
return Container(
|
|
|
|
margin: EdgeInsets.fromLTRB(6.w, 0, 14.w, 0),
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 6.h),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Color(0xFFF5FAF7),
|
|
|
|
borderRadius: BorderRadius.circular(4),
|
|
|
|
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());
|
|
|
|
loadFinish();
|
|
|
|
},
|
|
|
|
controller: editingController,
|
|
|
|
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,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool get wantKeepAlive => true;
|
|
|
|
}
|