import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/utils.dart'; import 'package:huixiang/constant.dart'; import 'package:huixiang/data/ip_data.dart'; import 'package:huixiang/data/mip_data.dart'; import 'package:huixiang/generated/l10n.dart'; import 'package:huixiang/main.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/utils/shared_preference.dart'; import 'package:huixiang/view_widget/my_tab.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:visibility_detector/visibility_detector.dart'; import '../data/address.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 createState() { return UnionPageState(); } } class UnionPageState extends State with AutomaticKeepAliveClientMixin, WidgetsBindingObserver, SingleTickerProviderStateMixin { final TextEditingController editingController = TextEditingController(); bool isKeyBoardShow = false; TabController? tabController; Position? latLng; String? areaName; List _allKey = []; bool _isShowLocalTips = false; double? visiblePercentage; jumpIndex(jpIndex) { tabController?.index = jpIndex; } @override void dispose() { super.dispose(); WidgetsBinding.instance.removeObserver(this); // Location.instance.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().listen((event) { if (event.type < 3) { setState(() {}); } }); queryIpInfo(); } Future isEmulator() async { DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); if (Platform.isAndroid) { AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; return !androidInfo.isPhysicalDevice; } else if (Platform.isIOS) { IosDeviceInfo iosInfo = await deviceInfo.iosInfo; return !iosInfo.isPhysicalDevice; } return false; } getLocation({bool showLoading = true}) async { if (showLoading && !(await isEmulator())) S.current.zhengzaijiazai.loading; bool powerFlag = false; // bool finallyFlag = false; try { powerFlag = await LocationInstance.getInstance().startLocation(context, (Position? result) async { if (result?.latitude != null && result?.longitude != null) { print("location: $result"); latLng = Position( latitude: result!.latitude, longitude: result.longitude, timestamp: DateTime.now(), accuracy: 0, altitude: 0, heading: 0, speed: 0, speedAccuracy: 0); Address? address = await LocationInstance.getInstance() .getAddress(result.latitude, result.longitude); if (address != null) { await saveLatLng( latLng!, address.province, address.city, address.area); areaName = address.city?.replaceAll("市", ""); } LocationInstance.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(Position latLng, String? province, String? city, String? district) async { SharedInstance.instance.saveLatLng(latLng); if (province?.isNotEmpty ?? false) SharedInstance.instance.setProvince(province); if (city?.isNotEmpty ?? false) SharedInstance.instance.setProvince(city); if (district?.isNotEmpty ?? false) SharedInstance.instance.setProvince(district); } getLatLng() async { if (SharedInstance.instance.language.isNotEmpty && SharedInstance.instance.longitude.isNotEmpty && SharedInstance.instance.province.isNotEmpty && SharedInstance.instance.city.isNotEmpty && SharedInstance.instance.district.isNotEmpty) { latLng = Position( latitude: double.tryParse(SharedInstance.instance.language)!, longitude: double.tryParse(SharedInstance.instance.longitude)!, timestamp: DateTime.now(), accuracy: 0, altitude: 0, heading: 0, speed: 0, speedAccuracy: 0, ); } } queryIpInfo() async { S.current.zhengzaijiazai.loading; try { ApiService apiIpService = ApiService(Dio(), context: context); String ipResult = await apiIpService.getIpInfo1().catchError((onError) { return ""; }); if (ipResult.isNotEmpty) { String string = ipResult.replaceAll("\n", ""); MIpData ipData = MIpData.fromJson(jsonDecode(string)); areaName = ipData.data?.location?[2]; } } finally { getLocation(showLoading: false); SmartDialog.dismiss(status: SmartStatus.loading); } } loadFinish({bool showLoading = true}) { SmartDialog.dismiss(status: SmartStatus.loading); if (showLoading) { S.current.zhengzaijiazai.loading; } _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, //tab排放方向 tabAlignment: TabAlignment.start, isScrollable: true, //可滚动 dividerHeight: 0, dividerColor: Colors.transparent, 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: [ 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; }