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.
329 lines
12 KiB
329 lines
12 KiB
import 'package:dio/dio.dart'; |
|
import 'package:flutter/cupertino.dart'; |
|
import 'package:flutter/material.dart'; |
|
import 'package:flutter_easyloading/flutter_easyloading.dart'; |
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
import 'package:geolocator/geolocator.dart'; |
|
import 'package:huixiang/generated/l10n.dart'; |
|
import 'package:huixiang/retrofit/retrofit_api.dart'; |
|
import 'package:huixiang/view_widget/request_permission.dart'; |
|
import 'package:intl/intl.dart'; |
|
import 'package:permission_handler/permission_handler.dart' as PH; |
|
|
|
import '../data/address.dart'; |
|
import 'font_weight.dart'; |
|
|
|
class LocationInstance { |
|
static LocationInstance? _instance; |
|
|
|
LocationInstance._internal() {} |
|
|
|
static LocationInstance getInstance() { |
|
if (_instance == null) { |
|
_instance = LocationInstance._internal(); |
|
} |
|
return _instance!; |
|
} |
|
|
|
Future<bool> startLocation( |
|
context, Function(Position? locationData) locationCallback) async { |
|
LocationPermission permissionStatus = await Geolocator.checkPermission(); |
|
if (permissionStatus == LocationPermission.denied) { |
|
permissionStatus = await Geolocator.requestPermission(); |
|
} |
|
if (permissionStatus == LocationPermission.denied) { |
|
showTipsAlertDialog(context); |
|
return false; |
|
} |
|
if (permissionStatus == LocationPermission.deniedForever) { |
|
showTipsAlertDialog(context); |
|
return false; |
|
} |
|
if (permissionStatus == LocationPermission.whileInUse || |
|
permissionStatus == LocationPermission.always) { |
|
bool isNext = true; |
|
Future.delayed(Duration(seconds: 5), () { |
|
if (isNext) { |
|
EasyLoading.dismiss(); |
|
} |
|
}); |
|
Position locationData = await Geolocator.getCurrentPosition( |
|
desiredAccuracy: LocationAccuracy.medium, |
|
timeLimit: const Duration(seconds: 30), |
|
forceAndroidLocationManager: true, |
|
); |
|
isNext = false; |
|
locationCallback.call(locationData); |
|
} |
|
return true; |
|
} |
|
|
|
void stopLocation() {} |
|
|
|
enableLocation(context) { |
|
showCupertinoDialog( |
|
context: context, |
|
builder: (context) { |
|
return RequestPermission( |
|
"assets/image/icon_permission_location_bg.webp", |
|
S.of(context).nindingweigongnengweikaiqi, |
|
S.of(context).weilexiangnintuijianfujindemendianxinxi, |
|
S.of(context).dakaidingwei, |
|
(result) async { |
|
if (result) { |
|
// final AndroidIntent intent = AndroidIntent( |
|
// action: 'action_location_source_settings', |
|
// package: "com.zsw.huixiang", |
|
// ); |
|
// await intent.launch(); |
|
Geolocator.openLocationSettings(); |
|
// startLocation(); |
|
} |
|
}, |
|
heightRatioWithWidth: 0.82, |
|
); |
|
}, |
|
); |
|
} |
|
|
|
requestDialog(context, Function(Position? result) locationCallback) { |
|
showCupertinoDialog( |
|
context: context, |
|
builder: (context) { |
|
return RequestPermission( |
|
"assets/image/icon_permission_location_bg.webp", |
|
S.of(context).nindingweiquanxianweiyunxu, |
|
S.of(context).weilexiangnintuijianfujindemendianxinxi, |
|
S.of(context).kaiqiquanxian, |
|
(result) async { |
|
if (result) { |
|
await PH.openAppSettings(); |
|
if ((await Geolocator.checkPermission()) == |
|
LocationPermission.whileInUse || |
|
(await Geolocator.checkPermission()) == |
|
LocationPermission.always) { |
|
startLocation(context, locationCallback); |
|
} |
|
} |
|
}, |
|
heightRatioWithWidth: 0.82, |
|
); |
|
}, |
|
); |
|
} |
|
|
|
///定位权限说明弹窗 |
|
showTipsAlertDialog(context) async { |
|
//显示对话框 |
|
showDialog( |
|
context: context, |
|
barrierDismissible: false, |
|
barrierColor: null, |
|
builder: (BuildContext context) { |
|
return Column( |
|
children: [ |
|
Container( |
|
width: double.infinity, |
|
padding: EdgeInsets.all(15), |
|
margin: EdgeInsets.all(15), |
|
decoration: new BoxDecoration( |
|
color: Colors.white, |
|
borderRadius: BorderRadius.circular(10), |
|
), |
|
child: Row( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Icon( |
|
Icons.location_on_outlined, |
|
color: Colors.black, |
|
size: 22, |
|
), |
|
Expanded( |
|
child: Column( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
mainAxisSize: MainAxisSize.min, |
|
children: [ |
|
Text( |
|
// "访问精确地理位置信息权限说明", |
|
"位置权限使用说明", |
|
style: TextStyle( |
|
fontSize: 18.sp, |
|
fontWeight: MyFontWeight.regular, |
|
color: Colors.black, |
|
), |
|
), |
|
SizedBox( |
|
height: 3.h, |
|
), |
|
Text( |
|
// "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", |
|
"为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息", |
|
style: TextStyle( |
|
fontSize: 13.sp, |
|
fontWeight: MyFontWeight.regular, |
|
color: Colors.black, |
|
), |
|
), |
|
], |
|
), |
|
), |
|
], |
|
), |
|
) |
|
], |
|
mainAxisSize: MainAxisSize.min, |
|
); |
|
}, |
|
); |
|
Geolocator.requestPermission(); |
|
Navigator.of(context).pop(); |
|
} |
|
|
|
///定位权限说明和申请弹窗 |
|
showAlertDialog(context) { |
|
//显示对话框 |
|
showDialog( |
|
context: context, |
|
barrierDismissible: true, |
|
barrierColor: null, |
|
builder: (BuildContext context) { |
|
return Column( |
|
children: [ |
|
Container( |
|
width: double.infinity, |
|
padding: EdgeInsets.all(15), |
|
margin: EdgeInsets.all(15), |
|
decoration: new BoxDecoration( |
|
color: Colors.black.withOpacity(0.6), |
|
borderRadius: BorderRadius.circular(10), |
|
), |
|
child: Row( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
children: [ |
|
Expanded( |
|
child: Column( |
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
mainAxisSize: MainAxisSize.min, |
|
children: [ |
|
Text( |
|
// "访问精确地理位置信息权限说明", |
|
"定位服务未开启", |
|
style: TextStyle( |
|
fontSize: 18.sp, |
|
fontWeight: MyFontWeight.regular, |
|
color: Colors.white, |
|
), |
|
), |
|
SizedBox( |
|
height: 3.h, |
|
), |
|
Text( |
|
// "为了向您推荐附近的门店信息,推荐您在使用期间让我们使用位置信息,不授权该权限不影响app正常使用。", |
|
"开启后才能提供更详细的定位服务哦!", |
|
style: TextStyle( |
|
fontSize: 13.sp, |
|
fontWeight: MyFontWeight.regular, |
|
color: Colors.white, |
|
), |
|
), |
|
], |
|
), |
|
), |
|
GestureDetector( |
|
child: Container( |
|
child: Text( |
|
"去开启", |
|
style: TextStyle( |
|
fontSize: 15.sp, |
|
fontWeight: MyFontWeight.regular, |
|
color: Colors.white, |
|
), |
|
), |
|
margin: EdgeInsets.symmetric( |
|
horizontal: 15.w, vertical: 25.h), |
|
padding: |
|
EdgeInsets.symmetric(vertical: 2.h, horizontal: 10.w), |
|
decoration: BoxDecoration( |
|
color: Colors.green, |
|
borderRadius: BorderRadius.circular(100), |
|
), |
|
), |
|
onTap: () async { |
|
await PH.openAppSettings(); |
|
if ((await Geolocator.checkPermission()) == |
|
LocationPermission.whileInUse || |
|
(await Geolocator.checkPermission()) == |
|
LocationPermission.always) |
|
Navigator.of(context).pop(); |
|
}, |
|
behavior: HitTestBehavior.opaque, |
|
), |
|
GestureDetector( |
|
behavior: HitTestBehavior.opaque, |
|
child: Container( |
|
child: Icon( |
|
Icons.close, |
|
color: Colors.white.withOpacity(0.8), |
|
size: 12, |
|
), |
|
decoration: BoxDecoration( |
|
color: Colors.black.withOpacity(0.8), |
|
borderRadius: BorderRadius.circular(100), |
|
), |
|
padding: EdgeInsets.all(5), |
|
), |
|
onTap: () { |
|
Navigator.of(context).pop(); |
|
}, |
|
) |
|
], |
|
), |
|
) |
|
], |
|
mainAxisSize: MainAxisSize.min, |
|
); |
|
}, |
|
); |
|
} |
|
|
|
///计算距离(当前位置到店位置直线距离) |
|
static Future<String> calculateDistance( |
|
Position bmfCoordinate, Position myLatLng, |
|
{bool isMi = false}) async { |
|
double mi = Geolocator.distanceBetween( |
|
bmfCoordinate.latitude, |
|
bmfCoordinate.longitude, |
|
myLatLng.latitude, |
|
myLatLng.longitude, |
|
); |
|
NumberFormat numberFormat = NumberFormat("#.#"); |
|
return "${numberFormat.format(mi / (isMi ? 1 : 1000))}"; |
|
} |
|
|
|
// ///坐标系转换(高德转百度) |
|
// static Future<Latlng> coordConvert(Latlng latLng) async { |
|
// return BMFCalculateUtils.coordConvert( |
|
// coordinate: latLng, |
|
// fromType: BMF_COORD_TYPE.COMMON, |
|
// toType: BMF_COORD_TYPE.BD09LL); |
|
// } |
|
|
|
Future<Address?>? getAddress(double lat, double lang) async { |
|
var result = await ApiService(Dio()).geocodeRegeo("$lat", "$lang"); |
|
print("address_result: $result"); |
|
if (result["status"] == "1" && |
|
result["regeocode"] != null && |
|
result["regeocode"]["addressComponent"] != null) { |
|
Address address = Address.fromJson({ |
|
"address": result["regeocode"]["formatted_address"], |
|
"area": result['regeocode']["addressComponent"]["district"], |
|
"city": result['regeocode']["addressComponent"]["city"], |
|
"latitude": lat, |
|
"longitude": lang, |
|
"province": result['regeocode']["addressComponent"]["province"], |
|
}); |
|
return address; |
|
} |
|
return null; |
|
} |
|
} |