Showing
10 changed files
with
3083 additions
and
1606 deletions
Too many changes to show.
To preserve performance only 10 of 10+ files are displayed.
| @@ -243,6 +243,26 @@ | @@ -243,6 +243,26 @@ | ||
| 243 | "flutterMode": "release" | 243 | "flutterMode": "release" |
| 244 | }, | 244 | }, |
| 245 | { | 245 | { |
| 246 | + "name": "flutter_tts_ohos", | ||
| 247 | + "cwd": "library/flutter_tts_ohos", | ||
| 248 | + "request": "launch", | ||
| 249 | + "type": "dart" | ||
| 250 | + }, | ||
| 251 | + { | ||
| 252 | + "name": "flutter_tts_ohos (profile mode)", | ||
| 253 | + "cwd": "library/flutter_tts_ohos", | ||
| 254 | + "request": "launch", | ||
| 255 | + "type": "dart", | ||
| 256 | + "flutterMode": "profile" | ||
| 257 | + }, | ||
| 258 | + { | ||
| 259 | + "name": "flutter_tts_ohos (release mode)", | ||
| 260 | + "cwd": "library/flutter_tts_ohos", | ||
| 261 | + "request": "launch", | ||
| 262 | + "type": "dart", | ||
| 263 | + "flutterMode": "release" | ||
| 264 | + }, | ||
| 265 | + { | ||
| 246 | "name": "fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new", | 266 | "name": "fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new", |
| 247 | "cwd": "library/fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new", | 267 | "cwd": "library/fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new", |
| 248 | "request": "launch", | 268 | "request": "launch", |
| @@ -323,6 +343,26 @@ | @@ -323,6 +343,26 @@ | ||
| 323 | "flutterMode": "release" | 343 | "flutterMode": "release" |
| 324 | }, | 344 | }, |
| 325 | { | 345 | { |
| 346 | + "name": "speech_to_text_wdn_ohos", | ||
| 347 | + "cwd": "library/speech_to_text_wdn_ohos", | ||
| 348 | + "request": "launch", | ||
| 349 | + "type": "dart" | ||
| 350 | + }, | ||
| 351 | + { | ||
| 352 | + "name": "speech_to_text_wdn_ohos (profile mode)", | ||
| 353 | + "cwd": "library/speech_to_text_wdn_ohos", | ||
| 354 | + "request": "launch", | ||
| 355 | + "type": "dart", | ||
| 356 | + "flutterMode": "profile" | ||
| 357 | + }, | ||
| 358 | + { | ||
| 359 | + "name": "speech_to_text_wdn_ohos (release mode)", | ||
| 360 | + "cwd": "library/speech_to_text_wdn_ohos", | ||
| 361 | + "request": "launch", | ||
| 362 | + "type": "dart", | ||
| 363 | + "flutterMode": "release" | ||
| 364 | + }, | ||
| 365 | + { | ||
| 326 | "name": "table_calendar-2.3.3", | 366 | "name": "table_calendar-2.3.3", |
| 327 | "cwd": "library/table_calendar-2.3.3", | 367 | "cwd": "library/table_calendar-2.3.3", |
| 328 | "request": "launch", | 368 | "request": "launch", |
| @@ -524,6 +564,26 @@ | @@ -524,6 +564,26 @@ | ||
| 524 | }, | 564 | }, |
| 525 | { | 565 | { |
| 526 | "name": "example", | 566 | "name": "example", |
| 567 | + "cwd": "library/flutter_tts_ohos/example", | ||
| 568 | + "request": "launch", | ||
| 569 | + "type": "dart" | ||
| 570 | + }, | ||
| 571 | + { | ||
| 572 | + "name": "example (profile mode)", | ||
| 573 | + "cwd": "library/flutter_tts_ohos/example", | ||
| 574 | + "request": "launch", | ||
| 575 | + "type": "dart", | ||
| 576 | + "flutterMode": "profile" | ||
| 577 | + }, | ||
| 578 | + { | ||
| 579 | + "name": "example (release mode)", | ||
| 580 | + "cwd": "library/flutter_tts_ohos/example", | ||
| 581 | + "request": "launch", | ||
| 582 | + "type": "dart", | ||
| 583 | + "flutterMode": "release" | ||
| 584 | + }, | ||
| 585 | + { | ||
| 586 | + "name": "example", | ||
| 527 | "cwd": "library/fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new/example", | 587 | "cwd": "library/fluttertpc_flutter_barcode_scanner-af5d0e6d2bc53977f979c4f2b852f46274dc8405_new/example", |
| 528 | "request": "launch", | 588 | "request": "launch", |
| 529 | "type": "dart" | 589 | "type": "dart" |
| @@ -644,6 +704,26 @@ | @@ -644,6 +704,26 @@ | ||
| 644 | }, | 704 | }, |
| 645 | { | 705 | { |
| 646 | "name": "example", | 706 | "name": "example", |
| 707 | + "cwd": "library/speech_to_text_wdn_ohos/example", | ||
| 708 | + "request": "launch", | ||
| 709 | + "type": "dart" | ||
| 710 | + }, | ||
| 711 | + { | ||
| 712 | + "name": "example (profile mode)", | ||
| 713 | + "cwd": "library/speech_to_text_wdn_ohos/example", | ||
| 714 | + "request": "launch", | ||
| 715 | + "type": "dart", | ||
| 716 | + "flutterMode": "profile" | ||
| 717 | + }, | ||
| 718 | + { | ||
| 719 | + "name": "example (release mode)", | ||
| 720 | + "cwd": "library/speech_to_text_wdn_ohos/example", | ||
| 721 | + "request": "launch", | ||
| 722 | + "type": "dart", | ||
| 723 | + "flutterMode": "release" | ||
| 724 | + }, | ||
| 725 | + { | ||
| 726 | + "name": "example", | ||
| 647 | "cwd": "library/table_calendar-3.1.3/example", | 727 | "cwd": "library/table_calendar-3.1.3/example", |
| 648 | "request": "launch", | 728 | "request": "launch", |
| 649 | "type": "dart" | 729 | "type": "dart" |
| @@ -8,8 +8,14 @@ | @@ -8,8 +8,14 @@ | ||
| 8 | additional functionality it is fine to subclass or reimplement | 8 | additional functionality it is fine to subclass or reimplement |
| 9 | FlutterApplication and put your custom class here. --> | 9 | FlutterApplication and put your custom class here. --> |
| 10 | 10 | ||
| 11 | - | ||
| 12 | - <!-- 【必须】 移动推送 TPNS SDK 所需权限 --> | 11 | + |
| 12 | + | ||
| 13 | + | ||
| 14 | + <uses-permission android:name="android.permission.RECORD_AUDIO"/> | ||
| 15 | + <uses-permission android:name="android.permission.BLUETOOTH"/> | ||
| 16 | + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> | ||
| 17 | + <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> | ||
| 18 | + | ||
| 13 | <uses-permission android:name="android.permission.INTERNET" /> | 19 | <uses-permission android:name="android.permission.INTERNET" /> |
| 14 | <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | 20 | <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> |
| 15 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | 21 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
| @@ -36,6 +42,13 @@ | @@ -36,6 +42,13 @@ | ||
| 36 | <uses-permission android:name="android.permission.READ_CALL_LOG" /> | 42 | <uses-permission android:name="android.permission.READ_CALL_LOG" /> |
| 37 | 43 | ||
| 38 | 44 | ||
| 45 | + <queries> | ||
| 46 | + <intent> | ||
| 47 | + <action android:name="android.speech.RecognitionService" /> | ||
| 48 | + </intent> | ||
| 49 | + </queries> | ||
| 50 | + | ||
| 51 | + | ||
| 39 | 52 | ||
| 40 | 53 | ||
| 41 | <application | 54 | <application |
| @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1536M | @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1536M | ||
| 3 | # android.enableR8=true | 3 | # android.enableR8=true |
| 4 | android.useAndroidX=true | 4 | android.useAndroidX=true |
| 5 | android.enableJetifier=true | 5 | android.enableJetifier=true |
| 6 | -android.suppressUnsupportedCompileSdk = 34 | 6 | +android.suppressUnsupportedCompileSdk=34,35 |
| 7 | org.gradle.warning.mode=all | 7 | org.gradle.warning.mode=all |
| 8 | 8 | ||
| 9 | # android.jetifier.blacklist=bcprov-jdk15on | 9 | # android.jetifier.blacklist=bcprov-jdk15on |
| 1 | -import 'package:csp_amap_flutter_base/csp_amap_flutter_base.dart'; | 1 | +// import 'package:csp_amap_flutter_base/csp_amap_flutter_base.dart'; |
| 2 | 2 | ||
| 3 | -class ConstConfig { | ||
| 4 | - static const AMapApiKey amapApiKeys = AMapApiKey( | ||
| 5 | - androidKey: '900f72eeee0f21e435cebb0ef155582a', //测试key | ||
| 6 | - iosKey: '4dfdec97b7bf0b8c13e94777103015a9', //测试key | ||
| 7 | - ohosKey: '7c2081e92ec65bfffa2df0a5464f0c7b'); //我的账户下面的ceshikey | ||
| 8 | - static const AMapPrivacyStatement amapPrivacyStatement = | ||
| 9 | - AMapPrivacyStatement(hasContains: true, hasShow: true, hasAgree: true); | ||
| 10 | -} | 3 | +// class ConstConfig { |
| 4 | +// static const AMapApiKey amapApiKeys = AMapApiKey( | ||
| 5 | +// androidKey: '900f72eeee0f21e435cebb0ef155582a', //测试key | ||
| 6 | +// iosKey: '4dfdec97b7bf0b8c13e94777103015a9', //测试key | ||
| 7 | +// ohosKey: '7c2081e92ec65bfffa2df0a5464f0c7b'); //我的账户下面的ceshikey | ||
| 8 | +// static const AMapPrivacyStatement amapPrivacyStatement = | ||
| 9 | +// AMapPrivacyStatement(hasContains: true, hasShow: true, hasAgree: true); | ||
| 10 | +// } |
| 1 | -// import 'dart:async'; | ||
| 2 | - | ||
| 3 | -// import 'package:amap_map_fluttify/amap_map_fluttify.dart'; | ||
| 4 | -// import 'package:flutter/cupertino.dart'; | ||
| 5 | - | ||
| 6 | -// import 'package:flutter/material.dart'; | ||
| 7 | - | ||
| 8 | -// import 'package:flutter_easyrefresh/easy_refresh.dart'; | ||
| 9 | - | ||
| 10 | - | ||
| 11 | -// import 'package:one_key/res/colors.dart'; | ||
| 12 | - | ||
| 13 | -// import 'package:one_key/utils/misc.dart'; | ||
| 14 | - | ||
| 15 | -// import 'package:one_key/utils/screen_util.dart'; | ||
| 16 | -// import 'package:one_key/utils/utils.dart'; | ||
| 17 | - | ||
| 18 | -// import 'package:one_key/widgets/system_app_bar.dart'; | ||
| 19 | -// import 'package:permission_handler/permission_handler.dart'; | ||
| 20 | - | ||
| 21 | -// import '../../utils/common_utils.dart'; | ||
| 22 | -// // import 'package:demo/resources/custom_text_style.dart'; | ||
| 23 | -// // import 'package:demo/utils/misc.dart'; | ||
| 24 | - | ||
| 25 | -// // import 'package:demo/widgets/network_state/page_loading.dart'; | ||
| 26 | - | ||
| 27 | -// class MapChoicePointPage extends StatefulWidget { | ||
| 28 | -// final String? long; | ||
| 29 | -// final String? lat; | ||
| 30 | -// MapChoicePointPage({Key? key, this.long, this.lat}) : super(key: key); | ||
| 31 | - | ||
| 32 | -// @override | ||
| 33 | -// _MapChoicePointPageState createState() => _MapChoicePointPageState(); | ||
| 34 | -// } | ||
| 35 | - | ||
| 36 | -// class _MapChoicePointPageState extends State<MapChoicePointPage> { | ||
| 37 | -// AmapController? _controller; | ||
| 38 | -// List<Poi>? poiList; | ||
| 39 | -// static List<PoiModel?> list = []; | ||
| 40 | -// static List<PoiModel> searchlist = []; | ||
| 41 | -// PoiModel? poiModel; | ||
| 42 | -// String keyword = ""; | ||
| 43 | -// String? address = ""; | ||
| 44 | -// bool isloading = true; | ||
| 45 | - | ||
| 46 | -// double latitude = 39.684670899; | ||
| 47 | -// double longitude = 118.17630045; | ||
| 48 | - | ||
| 49 | -// double latitudeLocation = 39.684670899; | ||
| 50 | -// double longitudeLocation = 118.17630045; | ||
| 51 | - | ||
| 52 | -// List<InputTip> inputTipDatas = []; | ||
| 53 | -// int page = 1; | ||
| 54 | -// EasyRefreshController refreshController = EasyRefreshController(); | ||
| 55 | -// bool flag = true; | ||
| 56 | - | ||
| 57 | -// @override | ||
| 58 | -// void initState() { | ||
| 59 | -// super.initState(); | ||
| 60 | - | ||
| 61 | -// if (widget.long != null && widget.long != '' && widget.long != 'null') { | ||
| 62 | -// longitude = double.parse(widget.long!); | ||
| 63 | -// } | ||
| 64 | -// if (widget.lat != null && widget.lat != '' && widget.lat != 'null') { | ||
| 65 | -// latitude = double.parse(widget.lat!); | ||
| 66 | -// } | ||
| 67 | - | ||
| 68 | -// WidgetsBinding.instance.addPostFrameCallback((_) async { | ||
| 69 | -// _requestLocationPermission(); | ||
| 70 | - | ||
| 71 | -// // ama | ||
| 72 | -// // let marker = new AMap.Marker({//添加标记点 | ||
| 73 | -// // position: this.position, | ||
| 74 | -// // map: map | ||
| 75 | -// }); | ||
| 76 | -// } | ||
| 77 | - | ||
| 78 | -// // Future<bool> checkLocationPermission() async { | ||
| 79 | -// // PermissionStatus permissionStatus = await Permission.location.status; | ||
| 80 | -// // if (permissionStatus == PermissionStatus.granted) { | ||
| 81 | -// // return true; | ||
| 82 | -// // } else { | ||
| 83 | -// // return false; | ||
| 84 | -// // } | ||
| 85 | -// // } | ||
| 86 | - | ||
| 87 | -// /// 检查权限并定 | ||
| 88 | -// // _getLocationPermission() async { | ||
| 89 | -// // if (!(await checkPermission(Permission.location))) { | ||
| 90 | -// // //没有定位权限 | ||
| 91 | - | ||
| 92 | -// // //申请定位权限 | ||
| 93 | -// // _requestLocationPermission(); | ||
| 94 | -// // } else { | ||
| 95 | -// // //去定位 | ||
| 96 | -// // _requestLocationPermission(); | ||
| 97 | -// // } | ||
| 98 | -// // } | ||
| 99 | - | ||
| 100 | -// /// 获取定位权限 | ||
| 101 | -// _requestLocationPermission() async { | ||
| 102 | -// await AmapLocation.instance.updatePrivacyShow(true); | ||
| 103 | -// await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 104 | -// bool canLocation = false; | ||
| 105 | - | ||
| 106 | -// if (!(await checkPermission(Permission.location))) { | ||
| 107 | -// //没有定位权限 | ||
| 108 | - | ||
| 109 | -// //申请定位权限 | ||
| 110 | -// canLocation = await requestPermission(Permission.location); | ||
| 111 | -// } else { | ||
| 112 | -// canLocation = true; | ||
| 113 | -// } | ||
| 114 | -// // bool canLocation = await requestPermission(Permission.location); | ||
| 115 | -// // 单次定位 | ||
| 116 | -// if (canLocation) { | ||
| 117 | -// Future.delayed(Duration(milliseconds: 200), () async { | ||
| 118 | -// await AmapLocation.instance.updatePrivacyShow(true); | ||
| 119 | -// await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 120 | -// final location = await AmapLocation.instance.fetchLocation( | ||
| 121 | -// // needAddress: true, | ||
| 122 | -// // mode: LocationAccuracy.High, | ||
| 123 | -// // timeout: Duration(seconds: 10) | ||
| 124 | -// ); | ||
| 125 | - | ||
| 126 | -// if (location.city == null || location.city == '') //网络不好,定位失败 | ||
| 127 | -// { | ||
| 128 | -// // App.sp.setString("lat", "39.684670899"); | ||
| 129 | -// // App.sp.setString("lng", "118.17630045"); | ||
| 130 | -// } else { | ||
| 131 | -// if (widget.long == null || | ||
| 132 | -// widget.long == '' || | ||
| 133 | -// widget.long == 'null') { | ||
| 134 | -// latitude = location.latLng!.latitude; | ||
| 135 | -// longitude = location.latLng!.longitude; | ||
| 136 | -// if (_controller != null) { | ||
| 137 | -// _controller!.setCenterCoordinate(LatLng( | ||
| 138 | -// location.latLng!.latitude, location.latLng!.longitude)); | ||
| 139 | -// } | ||
| 140 | - | ||
| 141 | -// page = 1; | ||
| 142 | - | ||
| 143 | -// _loadData( | ||
| 144 | -// LatLng(location.latLng!.latitude, location.latLng!.longitude)); | ||
| 145 | - | ||
| 146 | -// setState(() {}); | ||
| 147 | -// } | ||
| 148 | -// latitudeLocation = location.latLng!.latitude; | ||
| 149 | -// longitudeLocation = location.latLng!.longitude; | ||
| 150 | -// } | ||
| 151 | -// }); | ||
| 152 | -// } else { | ||
| 153 | -// //无权限 | ||
| 154 | -// } | ||
| 155 | -// } | ||
| 156 | - | ||
| 157 | -// @override | ||
| 158 | -// Widget build(BuildContext context) { | ||
| 159 | -// return Scaffold( | ||
| 160 | -// resizeToAvoidBottomInset: false, //防止底部布局被顶起 | ||
| 161 | -// appBar: SystemAppBar( | ||
| 162 | -// '选择位置信息', | ||
| 163 | -// onTap: () { | ||
| 164 | -// if (Navigator.canPop(context)) { | ||
| 165 | -// Navigator.pop(context); | ||
| 166 | -// } | ||
| 167 | -// }, | ||
| 168 | -// ), | ||
| 169 | - | ||
| 170 | -// body: Column( | ||
| 171 | -// children: <Widget>[ | ||
| 172 | -// // Theme( | ||
| 173 | -// // data: new | ||
| 174 | -// // ThemeData( | ||
| 175 | -// // // primaryColor: MyColours.color_438E93, | ||
| 176 | -// // // hintColor: MyColours.color_438E93), | ||
| 177 | -// // child: | ||
| 178 | -// // Container( | ||
| 179 | -// // color: MyColours.color_438E93, | ||
| 180 | -// // decoration: BoxDecoration( | ||
| 181 | -// // color: MyColours.color_438E93, | ||
| 182 | -// // boxShadow: [ | ||
| 183 | -// // BoxShadow(color: Colors.white, spreadRadius: 1), | ||
| 184 | -// // ], | ||
| 185 | -// // ), | ||
| 186 | - | ||
| 187 | -// // padding: EdgeInsets.all(5), | ||
| 188 | -// // child: | ||
| 189 | - | ||
| 190 | -// // ), | ||
| 191 | -// // ), | ||
| 192 | -// // ListView.builder( | ||
| 193 | -// // shrinkWrap: true, | ||
| 194 | -// // itemCount: inputTipDatas.length, | ||
| 195 | -// // itemBuilder: (context, index) { | ||
| 196 | -// // InputTip inputTip = inputTipDatas[index]; | ||
| 197 | -// // return InkWell( | ||
| 198 | -// // onTap: () { | ||
| 199 | -// // // searchAroundAddress(inputTip.name ?? ''); | ||
| 200 | -// // // searchPoiId(inputTip.poiId ?? ''); | ||
| 201 | -// // // _loadData(inputTip.coordinate ?? | ||
| 202 | -// // // LatLng(latitude, longitude)); | ||
| 203 | -// // }, | ||
| 204 | -// // child: Container( | ||
| 205 | -// // child: Row( | ||
| 206 | -// // children: [ | ||
| 207 | -// // Text( | ||
| 208 | -// // inputTip.name ?? '', | ||
| 209 | -// // style: TextStyle( | ||
| 210 | -// // fontSize: font(15), | ||
| 211 | -// // color: MyColours.color_515151), | ||
| 212 | -// // ), | ||
| 213 | -// // HEmptyView(10), | ||
| 214 | -// // Expanded( | ||
| 215 | -// // child: Text( | ||
| 216 | -// // (inputTip.district ?? '') + | ||
| 217 | -// // (inputTip.address ?? ''), | ||
| 218 | -// // style: TextStyle( | ||
| 219 | -// // fontSize: font(13), | ||
| 220 | -// // color: MyColours.color_999999), | ||
| 221 | -// // ), | ||
| 222 | -// // ), | ||
| 223 | -// // ], | ||
| 224 | -// // ))); | ||
| 225 | -// // }) | ||
| 226 | -// // ], | ||
| 227 | -// // ), | ||
| 228 | - | ||
| 229 | -// Stack( | ||
| 230 | -// children: [ | ||
| 231 | -// Container( | ||
| 232 | -// height: w(300), | ||
| 233 | -// child: Stack( | ||
| 234 | -// children: <Widget>[ | ||
| 235 | -// AmapView( | ||
| 236 | -// showZoomControl: false, | ||
| 237 | - | ||
| 238 | -// /// 是否显示指南针控件 | ||
| 239 | -// showCompass: true, | ||
| 240 | - | ||
| 241 | -// /// 是否显示比例尺控件 | ||
| 242 | -// showScaleControl: true, | ||
| 243 | - | ||
| 244 | -// /// 是否使能缩放手势 | ||
| 245 | -// zoomGesturesEnabled: true, | ||
| 246 | - | ||
| 247 | -// /// 是否使能滚动手势 | ||
| 248 | -// scrollGesturesEnabled: true, | ||
| 249 | - | ||
| 250 | -// /// 是否使能旋转手势 | ||
| 251 | -// rotateGestureEnabled: false, | ||
| 252 | -// centerCoordinate: LatLng(latitude, longitude), | ||
| 253 | -// maskDelay: Duration(milliseconds: 500), | ||
| 254 | -// zoomLevel: 19, | ||
| 255 | -// onMapCreated: (controller) async { | ||
| 256 | -// _controller = controller; | ||
| 257 | -// _controller! | ||
| 258 | -// .setCenterCoordinate(LatLng(latitude, longitude)); | ||
| 259 | -// // if (await requestPermission(PermissionGroup.location)) { | ||
| 260 | -// // await controller.showMyLocation(true); | ||
| 261 | -// // await controller?.showLocateControl(true); | ||
| 262 | -// // final latLng = await _controller?.getLocation( | ||
| 263 | -// // delay: Duration(seconds: 2)); | ||
| 264 | -// // await enableFluttifyLog(false); // 关闭log | ||
| 265 | -// // _loadData(latLng); | ||
| 266 | -// // } else { | ||
| 267 | -// // //无权限 | ||
| 268 | -// // _showLocPemWidget(); | ||
| 269 | -// // } | ||
| 270 | -// }, | ||
| 271 | -// // markers: [], | ||
| 272 | -// onMapMoveEnd: (MapMove move) async { | ||
| 273 | -// latitude = move.coordinate!.latitude; | ||
| 274 | -// longitude = move.coordinate!.longitude; | ||
| 275 | -// page = 1; | ||
| 276 | -// _loadData(move.coordinate!); | ||
| 277 | -// }, | ||
| 278 | -// ), | ||
| 279 | -// Center( | ||
| 280 | -// child: Icon( | ||
| 281 | -// Icons.place, | ||
| 282 | -// size: w(32), | ||
| 283 | -// color: Color(0xFFFF0000), | ||
| 284 | -// ), | ||
| 285 | -// ), | ||
| 286 | -// Positioned( | ||
| 287 | -// right: w(10), | ||
| 288 | -// bottom: w(10), | ||
| 289 | -// child: InkWell( | ||
| 290 | -// onTap: () { | ||
| 291 | -// _controller!.setCenterCoordinate( | ||
| 292 | -// LatLng(latitudeLocation, longitudeLocation)); | ||
| 293 | -// }, | ||
| 294 | -// child: Container( | ||
| 295 | -// decoration: BoxDecoration( | ||
| 296 | -// color: MyColours.color_ffffff, | ||
| 297 | -// borderRadius: BorderRadius.circular(r(5))), | ||
| 298 | -// padding: EdgeInsets.all(w(5)), | ||
| 299 | -// child: Image.asset( | ||
| 300 | -// Utils.getImgPath('location_map'), | ||
| 301 | -// width: w(25), | ||
| 302 | -// ), | ||
| 303 | -// )), | ||
| 304 | -// ) | ||
| 305 | -// ], | ||
| 306 | -// ), | ||
| 307 | -// ), | ||
| 308 | -// Positioned( | ||
| 309 | -// top: w(10), | ||
| 310 | -// left: w(20), | ||
| 311 | -// right: w(20), | ||
| 312 | -// child: Container( | ||
| 313 | -// // height: w(45), | ||
| 314 | -// padding: EdgeInsets.symmetric(vertical: w(10)), | ||
| 315 | -// decoration: BoxDecoration( | ||
| 316 | -// color: Colors.white, | ||
| 317 | -// borderRadius: BorderRadius.circular(r(10))), | ||
| 318 | -// child: TextField( | ||
| 319 | -// textAlignVertical: TextAlignVertical.center, | ||
| 320 | -// style: TextStyle( | ||
| 321 | -// color: MyColours.color_515151, | ||
| 322 | -// fontSize: font(15), | ||
| 323 | -// ), | ||
| 324 | -// controller: | ||
| 325 | -// TextEditingController.fromValue(TextEditingValue( | ||
| 326 | -// // 设置内容 | ||
| 327 | -// text: keyword, | ||
| 328 | -// selection: TextSelection.fromPosition(TextPosition( | ||
| 329 | -// affinity: TextAffinity.downstream, | ||
| 330 | -// offset: keyword.length)), | ||
| 331 | -// // 保持光标在最后 | ||
| 332 | -// )), | ||
| 333 | -// decoration: InputDecoration( | ||
| 334 | -// // border: b, | ||
| 335 | -// // border: OutlineInputBorder( | ||
| 336 | -// // borderRadius: BorderRadius.all(Radius.circular(40)), | ||
| 337 | -// // ), | ||
| 338 | -// border: OutlineInputBorder(borderSide: BorderSide.none), | ||
| 339 | -// hintText: '输入关键字', | ||
| 340 | -// isCollapsed: true, | ||
| 341 | - | ||
| 342 | -// hintStyle: TextStyle( | ||
| 343 | -// color: MyColours.color_999999, fontSize: font(15)), | ||
| 344 | -// // contentPadding: const EdgeInsets.symmetric( | ||
| 345 | -// // vertical: 8, horizontal: 1), | ||
| 346 | -// prefixIconConstraints: BoxConstraints(maxWidth: w(40)), | ||
| 347 | -// prefixIcon: Padding( | ||
| 348 | -// padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 349 | -// child: SizedBox( | ||
| 350 | -// width: w(30), | ||
| 351 | -// child: Image.asset( | ||
| 352 | -// Utils.getImgPath('search_black'), | ||
| 353 | -// ))), | ||
| 354 | -// suffixIconConstraints: BoxConstraints(maxWidth: w(32)), | ||
| 355 | -// suffixIcon: InkWell( | ||
| 356 | -// child: Padding( | ||
| 357 | -// padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 358 | -// child: SizedBox( | ||
| 359 | -// width: w(22), | ||
| 360 | -// child: Image.asset( | ||
| 361 | -// Utils.getImgPath('delete_black'), | ||
| 362 | -// ))), | ||
| 363 | -// onTap: () { | ||
| 364 | -// keyword = ""; | ||
| 365 | -// setState(() {}); | ||
| 366 | -// }, | ||
| 367 | -// ), | ||
| 368 | -// fillColor: Colors.white, | ||
| 369 | -// filled: true, | ||
| 370 | -// ), | ||
| 371 | - | ||
| 372 | -// inputFormatters: [], | ||
| 373 | -// //内容改变的回调 | ||
| 374 | -// onChanged: (text) { | ||
| 375 | -// print('change $text'); | ||
| 376 | -// keyword = text; | ||
| 377 | - | ||
| 378 | -// //搜索 | ||
| 379 | - | ||
| 380 | -// JhCommonUtils.debounce( | ||
| 381 | -// () => _fetchInputTips(text.toString())); | ||
| 382 | -// }, | ||
| 383 | -// //内容提交(按回车)的回调 | ||
| 384 | -// onSubmitted: (text) { | ||
| 385 | -// print('submit $text'); | ||
| 386 | -// // 触发关闭弹出来的键盘。 | ||
| 387 | -// keyword = text; | ||
| 388 | -// FocusScope.of(context).requestFocus(FocusNode()); | ||
| 389 | -// setState(() { | ||
| 390 | -// // isloading = true; | ||
| 391 | -// }); | ||
| 392 | - | ||
| 393 | -// // _fetchInputTips(text.toString()); | ||
| 394 | - | ||
| 395 | -// // searchAroundAddress(text.toString()); | ||
| 396 | -// }, | ||
| 397 | -// //按回车时调用 | ||
| 398 | -// onEditingComplete: () { | ||
| 399 | -// print('onEditingComplete'); | ||
| 400 | -// }, | ||
| 401 | -// ), | ||
| 402 | -// ), | ||
| 403 | -// ) | ||
| 404 | -// ], | ||
| 405 | -// ), | ||
| 406 | - | ||
| 407 | -// Expanded( | ||
| 408 | -// flex: 1, | ||
| 409 | -// child: Visibility( | ||
| 410 | -// visible: !isloading, | ||
| 411 | -// maintainSize: false, | ||
| 412 | -// maintainSemantics: false, | ||
| 413 | -// maintainInteractivity: false, | ||
| 414 | -// replacement: Center( | ||
| 415 | -// child: CupertinoActivityIndicator(), | ||
| 416 | -// ), | ||
| 417 | -// child: EasyRefresh.custom( | ||
| 418 | -// controller: refreshController, | ||
| 419 | -// slivers: [ | ||
| 420 | -// SliverList( | ||
| 421 | -// delegate: SliverChildBuilderDelegate( | ||
| 422 | -// (BuildContext context, int position) { | ||
| 423 | -// print("itemBuilder" + list.length.toString()); | ||
| 424 | -// PoiModel item = list[position]!; | ||
| 425 | -// return InkWell( | ||
| 426 | -// child: Column( | ||
| 427 | -// children: <Widget>[ | ||
| 428 | -// Container( | ||
| 429 | -// margin: EdgeInsets.only( | ||
| 430 | -// top: 8, bottom: 5, left: 10), | ||
| 431 | -// child: Row( | ||
| 432 | -// children: <Widget>[ | ||
| 433 | -// Icon( | ||
| 434 | -// Icons.place, | ||
| 435 | -// size: 20.0, | ||
| 436 | -// color: position == 0 | ||
| 437 | -// ? Colors.green | ||
| 438 | -// : Colors.grey, | ||
| 439 | -// ), | ||
| 440 | -// Expanded( | ||
| 441 | -// child: Text(item.title, | ||
| 442 | -// style: TextStyle( | ||
| 443 | -// fontSize: 16, | ||
| 444 | -// color: position == 0 | ||
| 445 | -// ? Colors.green | ||
| 446 | -// : Color(0xFF787878)))) | ||
| 447 | -// ], | ||
| 448 | -// ), | ||
| 449 | -// ), | ||
| 450 | -// Container( | ||
| 451 | -// margin: EdgeInsets.only( | ||
| 452 | -// top: 5, bottom: 5, left: 18), | ||
| 453 | -// alignment: Alignment.centerLeft, | ||
| 454 | -// child: Text( | ||
| 455 | -// item.address!, | ||
| 456 | -// style: TextStyle( | ||
| 457 | -// fontSize: 14, | ||
| 458 | -// color: Color(0xFF646464), | ||
| 459 | -// ), | ||
| 460 | -// ), | ||
| 461 | -// ), | ||
| 462 | -// Divider( | ||
| 463 | -// height: 1, | ||
| 464 | -// ) | ||
| 465 | -// ], | ||
| 466 | -// ), | ||
| 467 | -// onTap: () async { | ||
| 468 | -// // await _controller.setCenterCoordinate( | ||
| 469 | -// // LatLng(item.latLng.latitude, item.latLng.longitude), | ||
| 470 | -// // zoomLevel: 16); | ||
| 471 | -// if (Navigator.canPop(context)) { | ||
| 472 | -// Navigator.pop(context, { | ||
| 473 | -// 'address': item.address, | ||
| 474 | -// 'lat': item.latLng!.latitude.toString(), | ||
| 475 | -// 'lng': item.latLng!.longitude.toString() | ||
| 476 | -// }); | ||
| 477 | -// } | ||
| 478 | -// }, | ||
| 479 | -// ); | ||
| 480 | -// }, | ||
| 481 | -// childCount: list.length, | ||
| 482 | -// ), | ||
| 483 | -// ) | ||
| 484 | -// ], | ||
| 485 | -// onRefresh: () async { | ||
| 486 | -// if (flag) { | ||
| 487 | -// page = 1; | ||
| 488 | -// _loadData(LatLng(latitude, longitude)); | ||
| 489 | -// } | ||
| 490 | -// }, | ||
| 491 | -// onLoad: () async { | ||
| 492 | -// if (flag) { | ||
| 493 | -// page++; | ||
| 494 | -// _loadData(LatLng(latitude, longitude), | ||
| 495 | -// showloading: false); | ||
| 496 | -// } | ||
| 497 | -// }, | ||
| 498 | -// )), | ||
| 499 | -// ), | ||
| 500 | -// ], | ||
| 501 | -// ), | ||
| 502 | -// ); | ||
| 503 | -// } | ||
| 504 | - | ||
| 505 | -// _fetchInputTips(String text) async { | ||
| 506 | -// flag = false; | ||
| 507 | -// page = 1; | ||
| 508 | -// // setState(() { | ||
| 509 | -// // isloading = true; | ||
| 510 | -// // }); | ||
| 511 | - | ||
| 512 | -// /// 逆地理编码(坐标转地址) | ||
| 513 | -// /// | ||
| 514 | -// /// | ||
| 515 | -// await AmapLocation.instance.updatePrivacyShow(true); | ||
| 516 | -// await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 517 | - | ||
| 518 | -// LatLng latLng = LatLng(latitude, longitude); | ||
| 519 | -// ReGeocode reGeocodeList = await AmapSearch.instance.searchReGeocode(latLng); | ||
| 520 | - | ||
| 521 | -// // print(await reGeocodeList.toFutureString()); | ||
| 522 | -// address = reGeocodeList.formatAddress; | ||
| 523 | - | ||
| 524 | -// await AmapLocation.instance.updatePrivacyShow(true); | ||
| 525 | -// await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 526 | -// inputTipDatas = await AmapSearch.instance.fetchInputTips( | ||
| 527 | -// text, | ||
| 528 | -// city: "", | ||
| 529 | -// ); | ||
| 530 | -// print(inputTipDatas); | ||
| 531 | - | ||
| 532 | -// poiModel = new PoiModel("当前位置", address, latLng); | ||
| 533 | -// list.clear(); | ||
| 534 | -// list.add(poiModel); | ||
| 535 | -// for (var inputTip in inputTipDatas) { | ||
| 536 | -// String? title = await inputTip.name ?? ''; | ||
| 537 | -// String? cityStr = | ||
| 538 | -// await (inputTip.district ?? '') + (inputTip.address ?? ''); | ||
| 539 | - | ||
| 540 | -// LatLng? latLng = await inputTip.coordinate; | ||
| 541 | - | ||
| 542 | -// list.add(new PoiModel(title.toString(), cityStr, latLng)); | ||
| 543 | -// } | ||
| 544 | - | ||
| 545 | - | ||
| 546 | -// print(list); | ||
| 547 | - | ||
| 548 | -// setState(() { | ||
| 549 | -// // isloading = false; | ||
| 550 | -// }); | ||
| 551 | -// } | ||
| 552 | - | ||
| 553 | -// void _loadData(LatLng latLng, {showloading = true}) async { | ||
| 554 | -// flag = true; | ||
| 555 | -// setState(() { | ||
| 556 | -// if (showloading) { | ||
| 557 | -// isloading = true; | ||
| 558 | -// } | ||
| 559 | -// }); | ||
| 560 | - | ||
| 561 | -// /// 逆地理编码(坐标转地址) | ||
| 562 | -// /// | ||
| 563 | -// /// | ||
| 564 | - | ||
| 565 | -// await AmapLocation.instance.updatePrivacyShow(true); | ||
| 566 | -// await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 567 | -// if (page == 1) { | ||
| 568 | -// ReGeocode reGeocodeList = await AmapSearch.instance.searchReGeocode( | ||
| 569 | -// latLng, | ||
| 570 | -// ); | ||
| 571 | -// // print(await reGeocodeList.toFutureString()); | ||
| 572 | -// address = reGeocodeList.formatAddress; | ||
| 573 | -// poiModel = new PoiModel("当前位置", address, latLng); | ||
| 574 | -// list.clear(); | ||
| 575 | -// list.add(poiModel); | ||
| 576 | -// } | ||
| 577 | -// final poiList = | ||
| 578 | -// await AmapSearch.instance.searchAround(latLng, city: "", page: page); | ||
| 579 | - | ||
| 580 | -// for (var poi in poiList) { | ||
| 581 | -// String? title = await poi.title; | ||
| 582 | -// String? cityName = await poi.cityName; | ||
| 583 | -// String? provinceName = await poi.provinceName; | ||
| 584 | -// String? address = await poi.address; | ||
| 585 | -// LatLng? latLng = await poi.latLng; | ||
| 586 | -// String? bussniss = poi.businessArea; | ||
| 587 | - | ||
| 588 | -// list.add(new PoiModel( | ||
| 589 | -// title.toString(), | ||
| 590 | -// provinceName.toString() + | ||
| 591 | -// cityName.toString() + | ||
| 592 | -// address.toString() + | ||
| 593 | -// bussniss.toString(), | ||
| 594 | -// latLng)); | ||
| 595 | -// } | ||
| 596 | - | ||
| 597 | -// setState(() { | ||
| 598 | -// if (showloading) { | ||
| 599 | -// isloading = false; | ||
| 600 | -// } | ||
| 601 | -// }); | ||
| 602 | -// } | ||
| 603 | - | ||
| 604 | -// // void searchPoiId(String text) async { | ||
| 605 | -// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 606 | -// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 607 | -// // Poi? poi = await AmapSearch.instance.searchPoiId( | ||
| 608 | -// // text, | ||
| 609 | -// // ); | ||
| 610 | -// // print(poi); | ||
| 611 | -// // } | ||
| 612 | - | ||
| 613 | -// // void searchAroundAddress(String text) async { | ||
| 614 | -// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 615 | -// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 616 | -// // final poiList = await AmapSearch.instance.searchKeyword( | ||
| 617 | -// // text, | ||
| 618 | -// // city: "", | ||
| 619 | -// // ); | ||
| 620 | -// // // final poiList = await AmapSearch.instance.searchAround( | ||
| 621 | -// // // LatLng(latitude, longitude), | ||
| 622 | -// // // city: "", | ||
| 623 | -// // // radius: 100000000000000 | ||
| 624 | - | ||
| 625 | -// // // ); | ||
| 626 | - | ||
| 627 | -// // list.clear(); | ||
| 628 | -// // list.add(poiModel); | ||
| 629 | -// // for (var poi in poiList) { | ||
| 630 | -// // String? title = await poi.title; | ||
| 631 | -// // LatLng? latLng = await poi.latLng; | ||
| 632 | -// // String? cityName = await poi.cityName; | ||
| 633 | -// // String? provinceName = await poi.provinceName; | ||
| 634 | -// // String? address = await poi.address; | ||
| 635 | -// // list.add(new PoiModel( | ||
| 636 | -// // title.toString(), | ||
| 637 | -// // provinceName.toString() + cityName.toString() + address.toString(), | ||
| 638 | -// // latLng)); | ||
| 639 | -// // } | ||
| 640 | -// // setState(() { | ||
| 641 | -// // isloading = false; | ||
| 642 | -// // FocusScope.of(context).requestFocus(FocusNode()); | ||
| 643 | -// // }); | ||
| 644 | -// // } | ||
| 645 | -// } | ||
| 646 | - | ||
| 647 | -// class PoiModel { | ||
| 648 | -// LatLng? latLng; | ||
| 649 | -// String title; | ||
| 650 | -// String? address; | ||
| 651 | - | ||
| 652 | -// PoiModel(this.title, this.address, this.latLng); | ||
| 653 | -// } | 1 | +import 'dart:async'; |
| 2 | + | ||
| 3 | +import 'package:amap_map_fluttify/amap_map_fluttify.dart'; | ||
| 4 | +import 'package:flutter/cupertino.dart'; | ||
| 5 | + | ||
| 6 | +import 'package:flutter/material.dart'; | ||
| 7 | + | ||
| 8 | +import 'package:flutter_easyrefresh/easy_refresh.dart'; | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +import 'package:one_key/res/colors.dart'; | ||
| 12 | + | ||
| 13 | +import 'package:one_key/utils/misc.dart'; | ||
| 14 | + | ||
| 15 | +import 'package:one_key/utils/screen_util.dart'; | ||
| 16 | +import 'package:one_key/utils/utils.dart'; | ||
| 17 | + | ||
| 18 | +import 'package:one_key/widgets/system_app_bar.dart'; | ||
| 19 | +import 'package:permission_handler/permission_handler.dart'; | ||
| 20 | + | ||
| 21 | +import '../../utils/common_utils.dart'; | ||
| 22 | +// import 'package:demo/resources/custom_text_style.dart'; | ||
| 23 | +// import 'package:demo/utils/misc.dart'; | ||
| 24 | + | ||
| 25 | +// import 'package:demo/widgets/network_state/page_loading.dart'; | ||
| 26 | + | ||
| 27 | +class MapChoicePointPage extends StatefulWidget { | ||
| 28 | + final String? long; | ||
| 29 | + final String? lat; | ||
| 30 | + MapChoicePointPage({Key? key, this.long, this.lat}) : super(key: key); | ||
| 31 | + | ||
| 32 | + @override | ||
| 33 | + _MapChoicePointPageState createState() => _MapChoicePointPageState(); | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +class _MapChoicePointPageState extends State<MapChoicePointPage> { | ||
| 37 | + AmapController? _controller; | ||
| 38 | + List<Poi>? poiList; | ||
| 39 | + static List<PoiModel?> list = []; | ||
| 40 | + static List<PoiModel> searchlist = []; | ||
| 41 | + PoiModel? poiModel; | ||
| 42 | + String keyword = ""; | ||
| 43 | + String? address = ""; | ||
| 44 | + bool isloading = true; | ||
| 45 | + | ||
| 46 | + double latitude = 39.684670899; | ||
| 47 | + double longitude = 118.17630045; | ||
| 48 | + | ||
| 49 | + double latitudeLocation = 39.684670899; | ||
| 50 | + double longitudeLocation = 118.17630045; | ||
| 51 | + | ||
| 52 | + List<InputTip> inputTipDatas = []; | ||
| 53 | + int page = 1; | ||
| 54 | + EasyRefreshController refreshController = EasyRefreshController(); | ||
| 55 | + bool flag = true; | ||
| 56 | + | ||
| 57 | + @override | ||
| 58 | + void initState() { | ||
| 59 | + super.initState(); | ||
| 60 | + | ||
| 61 | + if (widget.long != null && widget.long != '' && widget.long != 'null') { | ||
| 62 | + longitude = double.parse(widget.long!); | ||
| 63 | + } | ||
| 64 | + if (widget.lat != null && widget.lat != '' && widget.lat != 'null') { | ||
| 65 | + latitude = double.parse(widget.lat!); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + WidgetsBinding.instance.addPostFrameCallback((_) async { | ||
| 69 | + _requestLocationPermission(); | ||
| 70 | + | ||
| 71 | + // ama | ||
| 72 | + // let marker = new AMap.Marker({//添加标记点 | ||
| 73 | + // position: this.position, | ||
| 74 | + // map: map | ||
| 75 | + }); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + // Future<bool> checkLocationPermission() async { | ||
| 79 | + // PermissionStatus permissionStatus = await Permission.location.status; | ||
| 80 | + // if (permissionStatus == PermissionStatus.granted) { | ||
| 81 | + // return true; | ||
| 82 | + // } else { | ||
| 83 | + // return false; | ||
| 84 | + // } | ||
| 85 | + // } | ||
| 86 | + | ||
| 87 | + /// 检查权限并定 | ||
| 88 | + // _getLocationPermission() async { | ||
| 89 | + // if (!(await checkPermission(Permission.location))) { | ||
| 90 | + // //没有定位权限 | ||
| 91 | + | ||
| 92 | + // //申请定位权限 | ||
| 93 | + // _requestLocationPermission(); | ||
| 94 | + // } else { | ||
| 95 | + // //去定位 | ||
| 96 | + // _requestLocationPermission(); | ||
| 97 | + // } | ||
| 98 | + // } | ||
| 99 | + | ||
| 100 | + /// 获取定位权限 | ||
| 101 | + _requestLocationPermission() async { | ||
| 102 | + await AmapLocation.instance.updatePrivacyShow(true); | ||
| 103 | + await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 104 | + bool canLocation = false; | ||
| 105 | + | ||
| 106 | + if (!(await checkPermission(Permission.location))) { | ||
| 107 | + //没有定位权限 | ||
| 108 | + | ||
| 109 | + //申请定位权限 | ||
| 110 | + canLocation = await requestPermission(Permission.location); | ||
| 111 | + } else { | ||
| 112 | + canLocation = true; | ||
| 113 | + } | ||
| 114 | + // bool canLocation = await requestPermission(Permission.location); | ||
| 115 | + // 单次定位 | ||
| 116 | + if (canLocation) { | ||
| 117 | + Future.delayed(Duration(milliseconds: 200), () async { | ||
| 118 | + await AmapLocation.instance.updatePrivacyShow(true); | ||
| 119 | + await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 120 | + final location = await AmapLocation.instance.fetchLocation( | ||
| 121 | + // needAddress: true, | ||
| 122 | + // mode: LocationAccuracy.High, | ||
| 123 | + // timeout: Duration(seconds: 10) | ||
| 124 | + ); | ||
| 125 | + | ||
| 126 | + if (location.city == null || location.city == '') //网络不好,定位失败 | ||
| 127 | + { | ||
| 128 | + // App.sp.setString("lat", "39.684670899"); | ||
| 129 | + // App.sp.setString("lng", "118.17630045"); | ||
| 130 | + } else { | ||
| 131 | + if (widget.long == null || | ||
| 132 | + widget.long == '' || | ||
| 133 | + widget.long == 'null') { | ||
| 134 | + latitude = location.latLng!.latitude; | ||
| 135 | + longitude = location.latLng!.longitude; | ||
| 136 | + if (_controller != null) { | ||
| 137 | + _controller!.setCenterCoordinate(LatLng( | ||
| 138 | + location.latLng!.latitude, location.latLng!.longitude)); | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + page = 1; | ||
| 142 | + | ||
| 143 | + _loadData( | ||
| 144 | + LatLng(location.latLng!.latitude, location.latLng!.longitude)); | ||
| 145 | + | ||
| 146 | + setState(() {}); | ||
| 147 | + } | ||
| 148 | + latitudeLocation = location.latLng!.latitude; | ||
| 149 | + longitudeLocation = location.latLng!.longitude; | ||
| 150 | + } | ||
| 151 | + }); | ||
| 152 | + } else { | ||
| 153 | + //无权限 | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + @override | ||
| 158 | + Widget build(BuildContext context) { | ||
| 159 | + return Scaffold( | ||
| 160 | + resizeToAvoidBottomInset: false, //防止底部布局被顶起 | ||
| 161 | + appBar: SystemAppBar( | ||
| 162 | + '选择位置信息', | ||
| 163 | + onTap: () { | ||
| 164 | + if (Navigator.canPop(context)) { | ||
| 165 | + Navigator.pop(context); | ||
| 166 | + } | ||
| 167 | + }, | ||
| 168 | + ), | ||
| 169 | + | ||
| 170 | + body: Column( | ||
| 171 | + children: <Widget>[ | ||
| 172 | + // Theme( | ||
| 173 | + // data: new | ||
| 174 | + // ThemeData( | ||
| 175 | + // // primaryColor: MyColours.color_438E93, | ||
| 176 | + // // hintColor: MyColours.color_438E93), | ||
| 177 | + // child: | ||
| 178 | + // Container( | ||
| 179 | + // color: MyColours.color_438E93, | ||
| 180 | + // decoration: BoxDecoration( | ||
| 181 | + // color: MyColours.color_438E93, | ||
| 182 | + // boxShadow: [ | ||
| 183 | + // BoxShadow(color: Colors.white, spreadRadius: 1), | ||
| 184 | + // ], | ||
| 185 | + // ), | ||
| 186 | + | ||
| 187 | + // padding: EdgeInsets.all(5), | ||
| 188 | + // child: | ||
| 189 | + | ||
| 190 | + // ), | ||
| 191 | + // ), | ||
| 192 | + // ListView.builder( | ||
| 193 | + // shrinkWrap: true, | ||
| 194 | + // itemCount: inputTipDatas.length, | ||
| 195 | + // itemBuilder: (context, index) { | ||
| 196 | + // InputTip inputTip = inputTipDatas[index]; | ||
| 197 | + // return InkWell( | ||
| 198 | + // onTap: () { | ||
| 199 | + // // searchAroundAddress(inputTip.name ?? ''); | ||
| 200 | + // // searchPoiId(inputTip.poiId ?? ''); | ||
| 201 | + // // _loadData(inputTip.coordinate ?? | ||
| 202 | + // // LatLng(latitude, longitude)); | ||
| 203 | + // }, | ||
| 204 | + // child: Container( | ||
| 205 | + // child: Row( | ||
| 206 | + // children: [ | ||
| 207 | + // Text( | ||
| 208 | + // inputTip.name ?? '', | ||
| 209 | + // style: TextStyle( | ||
| 210 | + // fontSize: font(15), | ||
| 211 | + // color: MyColours.color_515151), | ||
| 212 | + // ), | ||
| 213 | + // HEmptyView(10), | ||
| 214 | + // Expanded( | ||
| 215 | + // child: Text( | ||
| 216 | + // (inputTip.district ?? '') + | ||
| 217 | + // (inputTip.address ?? ''), | ||
| 218 | + // style: TextStyle( | ||
| 219 | + // fontSize: font(13), | ||
| 220 | + // color: MyColours.color_999999), | ||
| 221 | + // ), | ||
| 222 | + // ), | ||
| 223 | + // ], | ||
| 224 | + // ))); | ||
| 225 | + // }) | ||
| 226 | + // ], | ||
| 227 | + // ), | ||
| 228 | + | ||
| 229 | + Stack( | ||
| 230 | + children: [ | ||
| 231 | + Container( | ||
| 232 | + height: w(300), | ||
| 233 | + child: Stack( | ||
| 234 | + children: <Widget>[ | ||
| 235 | + AmapView( | ||
| 236 | + showZoomControl: false, | ||
| 237 | + | ||
| 238 | + /// 是否显示指南针控件 | ||
| 239 | + showCompass: true, | ||
| 240 | + | ||
| 241 | + /// 是否显示比例尺控件 | ||
| 242 | + showScaleControl: true, | ||
| 243 | + | ||
| 244 | + /// 是否使能缩放手势 | ||
| 245 | + zoomGesturesEnabled: true, | ||
| 246 | + | ||
| 247 | + /// 是否使能滚动手势 | ||
| 248 | + scrollGesturesEnabled: true, | ||
| 249 | + | ||
| 250 | + /// 是否使能旋转手势 | ||
| 251 | + rotateGestureEnabled: false, | ||
| 252 | + centerCoordinate: LatLng(latitude, longitude), | ||
| 253 | + maskDelay: Duration(milliseconds: 500), | ||
| 254 | + zoomLevel: 19, | ||
| 255 | + onMapCreated: (controller) async { | ||
| 256 | + _controller = controller; | ||
| 257 | + _controller! | ||
| 258 | + .setCenterCoordinate(LatLng(latitude, longitude)); | ||
| 259 | + // if (await requestPermission(PermissionGroup.location)) { | ||
| 260 | + // await controller.showMyLocation(true); | ||
| 261 | + // await controller?.showLocateControl(true); | ||
| 262 | + // final latLng = await _controller?.getLocation( | ||
| 263 | + // delay: Duration(seconds: 2)); | ||
| 264 | + // await enableFluttifyLog(false); // 关闭log | ||
| 265 | + // _loadData(latLng); | ||
| 266 | + // } else { | ||
| 267 | + // //无权限 | ||
| 268 | + // _showLocPemWidget(); | ||
| 269 | + // } | ||
| 270 | + }, | ||
| 271 | + // markers: [], | ||
| 272 | + onMapMoveEnd: (MapMove move) async { | ||
| 273 | + latitude = move.coordinate!.latitude; | ||
| 274 | + longitude = move.coordinate!.longitude; | ||
| 275 | + page = 1; | ||
| 276 | + _loadData(move.coordinate!); | ||
| 277 | + }, | ||
| 278 | + ), | ||
| 279 | + Center( | ||
| 280 | + child: Icon( | ||
| 281 | + Icons.place, | ||
| 282 | + size: w(32), | ||
| 283 | + color: Color(0xFFFF0000), | ||
| 284 | + ), | ||
| 285 | + ), | ||
| 286 | + Positioned( | ||
| 287 | + right: w(10), | ||
| 288 | + bottom: w(10), | ||
| 289 | + child: InkWell( | ||
| 290 | + onTap: () { | ||
| 291 | + _controller!.setCenterCoordinate( | ||
| 292 | + LatLng(latitudeLocation, longitudeLocation)); | ||
| 293 | + }, | ||
| 294 | + child: Container( | ||
| 295 | + decoration: BoxDecoration( | ||
| 296 | + color: MyColours.color_ffffff, | ||
| 297 | + borderRadius: BorderRadius.circular(r(5))), | ||
| 298 | + padding: EdgeInsets.all(w(5)), | ||
| 299 | + child: Image.asset( | ||
| 300 | + Utils.getImgPath('location_map'), | ||
| 301 | + width: w(25), | ||
| 302 | + ), | ||
| 303 | + )), | ||
| 304 | + ) | ||
| 305 | + ], | ||
| 306 | + ), | ||
| 307 | + ), | ||
| 308 | + Positioned( | ||
| 309 | + top: w(10), | ||
| 310 | + left: w(20), | ||
| 311 | + right: w(20), | ||
| 312 | + child: Container( | ||
| 313 | + // height: w(45), | ||
| 314 | + padding: EdgeInsets.symmetric(vertical: w(10)), | ||
| 315 | + decoration: BoxDecoration( | ||
| 316 | + color: Colors.white, | ||
| 317 | + borderRadius: BorderRadius.circular(r(10))), | ||
| 318 | + child: TextField( | ||
| 319 | + textAlignVertical: TextAlignVertical.center, | ||
| 320 | + style: TextStyle( | ||
| 321 | + color: MyColours.color_515151, | ||
| 322 | + fontSize: font(15), | ||
| 323 | + ), | ||
| 324 | + controller: | ||
| 325 | + TextEditingController.fromValue(TextEditingValue( | ||
| 326 | + // 设置内容 | ||
| 327 | + text: keyword, | ||
| 328 | + selection: TextSelection.fromPosition(TextPosition( | ||
| 329 | + affinity: TextAffinity.downstream, | ||
| 330 | + offset: keyword.length)), | ||
| 331 | + // 保持光标在最后 | ||
| 332 | + )), | ||
| 333 | + decoration: InputDecoration( | ||
| 334 | + // border: b, | ||
| 335 | + // border: OutlineInputBorder( | ||
| 336 | + // borderRadius: BorderRadius.all(Radius.circular(40)), | ||
| 337 | + // ), | ||
| 338 | + border: OutlineInputBorder(borderSide: BorderSide.none), | ||
| 339 | + hintText: '输入关键字', | ||
| 340 | + isCollapsed: true, | ||
| 341 | + | ||
| 342 | + hintStyle: TextStyle( | ||
| 343 | + color: MyColours.color_999999, fontSize: font(15)), | ||
| 344 | + // contentPadding: const EdgeInsets.symmetric( | ||
| 345 | + // vertical: 8, horizontal: 1), | ||
| 346 | + prefixIconConstraints: BoxConstraints(maxWidth: w(40)), | ||
| 347 | + prefixIcon: Padding( | ||
| 348 | + padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 349 | + child: SizedBox( | ||
| 350 | + width: w(30), | ||
| 351 | + child: Image.asset( | ||
| 352 | + Utils.getImgPath('search_black'), | ||
| 353 | + ))), | ||
| 354 | + suffixIconConstraints: BoxConstraints(maxWidth: w(32)), | ||
| 355 | + suffixIcon: InkWell( | ||
| 356 | + child: Padding( | ||
| 357 | + padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 358 | + child: SizedBox( | ||
| 359 | + width: w(22), | ||
| 360 | + child: Image.asset( | ||
| 361 | + Utils.getImgPath('delete_black'), | ||
| 362 | + ))), | ||
| 363 | + onTap: () { | ||
| 364 | + keyword = ""; | ||
| 365 | + setState(() {}); | ||
| 366 | + }, | ||
| 367 | + ), | ||
| 368 | + fillColor: Colors.white, | ||
| 369 | + filled: true, | ||
| 370 | + ), | ||
| 371 | + | ||
| 372 | + inputFormatters: [], | ||
| 373 | + //内容改变的回调 | ||
| 374 | + onChanged: (text) { | ||
| 375 | + print('change $text'); | ||
| 376 | + keyword = text; | ||
| 377 | + | ||
| 378 | + //搜索 | ||
| 379 | + | ||
| 380 | + JhCommonUtils.debounce( | ||
| 381 | + () => _fetchInputTips(text.toString())); | ||
| 382 | + }, | ||
| 383 | + //内容提交(按回车)的回调 | ||
| 384 | + onSubmitted: (text) { | ||
| 385 | + print('submit $text'); | ||
| 386 | + // 触发关闭弹出来的键盘。 | ||
| 387 | + keyword = text; | ||
| 388 | + FocusScope.of(context).requestFocus(FocusNode()); | ||
| 389 | + setState(() { | ||
| 390 | + // isloading = true; | ||
| 391 | + }); | ||
| 392 | + | ||
| 393 | + // _fetchInputTips(text.toString()); | ||
| 394 | + | ||
| 395 | + // searchAroundAddress(text.toString()); | ||
| 396 | + }, | ||
| 397 | + //按回车时调用 | ||
| 398 | + onEditingComplete: () { | ||
| 399 | + print('onEditingComplete'); | ||
| 400 | + }, | ||
| 401 | + ), | ||
| 402 | + ), | ||
| 403 | + ) | ||
| 404 | + ], | ||
| 405 | + ), | ||
| 406 | + | ||
| 407 | + Expanded( | ||
| 408 | + flex: 1, | ||
| 409 | + child: Visibility( | ||
| 410 | + visible: !isloading, | ||
| 411 | + maintainSize: false, | ||
| 412 | + maintainSemantics: false, | ||
| 413 | + maintainInteractivity: false, | ||
| 414 | + replacement: Center( | ||
| 415 | + child: CupertinoActivityIndicator(), | ||
| 416 | + ), | ||
| 417 | + child: EasyRefresh.custom( | ||
| 418 | + controller: refreshController, | ||
| 419 | + slivers: [ | ||
| 420 | + SliverList( | ||
| 421 | + delegate: SliverChildBuilderDelegate( | ||
| 422 | + (BuildContext context, int position) { | ||
| 423 | + print("itemBuilder" + list.length.toString()); | ||
| 424 | + PoiModel item = list[position]!; | ||
| 425 | + return InkWell( | ||
| 426 | + child: Column( | ||
| 427 | + children: <Widget>[ | ||
| 428 | + Container( | ||
| 429 | + margin: EdgeInsets.only( | ||
| 430 | + top: 8, bottom: 5, left: 10), | ||
| 431 | + child: Row( | ||
| 432 | + children: <Widget>[ | ||
| 433 | + Icon( | ||
| 434 | + Icons.place, | ||
| 435 | + size: 20.0, | ||
| 436 | + color: position == 0 | ||
| 437 | + ? Colors.green | ||
| 438 | + : Colors.grey, | ||
| 439 | + ), | ||
| 440 | + Expanded( | ||
| 441 | + child: Text(item.title, | ||
| 442 | + style: TextStyle( | ||
| 443 | + fontSize: 16, | ||
| 444 | + color: position == 0 | ||
| 445 | + ? Colors.green | ||
| 446 | + : Color(0xFF787878)))) | ||
| 447 | + ], | ||
| 448 | + ), | ||
| 449 | + ), | ||
| 450 | + Container( | ||
| 451 | + margin: EdgeInsets.only( | ||
| 452 | + top: 5, bottom: 5, left: 18), | ||
| 453 | + alignment: Alignment.centerLeft, | ||
| 454 | + child: Text( | ||
| 455 | + item.address!, | ||
| 456 | + style: TextStyle( | ||
| 457 | + fontSize: 14, | ||
| 458 | + color: Color(0xFF646464), | ||
| 459 | + ), | ||
| 460 | + ), | ||
| 461 | + ), | ||
| 462 | + Divider( | ||
| 463 | + height: 1, | ||
| 464 | + ) | ||
| 465 | + ], | ||
| 466 | + ), | ||
| 467 | + onTap: () async { | ||
| 468 | + // await _controller.setCenterCoordinate( | ||
| 469 | + // LatLng(item.latLng.latitude, item.latLng.longitude), | ||
| 470 | + // zoomLevel: 16); | ||
| 471 | + if (Navigator.canPop(context)) { | ||
| 472 | + Navigator.pop(context, { | ||
| 473 | + 'address': item.address, | ||
| 474 | + 'lat': item.latLng!.latitude.toString(), | ||
| 475 | + 'lng': item.latLng!.longitude.toString() | ||
| 476 | + }); | ||
| 477 | + } | ||
| 478 | + }, | ||
| 479 | + ); | ||
| 480 | + }, | ||
| 481 | + childCount: list.length, | ||
| 482 | + ), | ||
| 483 | + ) | ||
| 484 | + ], | ||
| 485 | + onRefresh: () async { | ||
| 486 | + if (flag) { | ||
| 487 | + page = 1; | ||
| 488 | + _loadData(LatLng(latitude, longitude)); | ||
| 489 | + } | ||
| 490 | + }, | ||
| 491 | + onLoad: () async { | ||
| 492 | + if (flag) { | ||
| 493 | + page++; | ||
| 494 | + _loadData(LatLng(latitude, longitude), | ||
| 495 | + showloading: false); | ||
| 496 | + } | ||
| 497 | + }, | ||
| 498 | + )), | ||
| 499 | + ), | ||
| 500 | + ], | ||
| 501 | + ), | ||
| 502 | + ); | ||
| 503 | + } | ||
| 504 | + | ||
| 505 | + _fetchInputTips(String text) async { | ||
| 506 | + flag = false; | ||
| 507 | + page = 1; | ||
| 508 | + // setState(() { | ||
| 509 | + // isloading = true; | ||
| 510 | + // }); | ||
| 511 | + | ||
| 512 | + /// 逆地理编码(坐标转地址) | ||
| 513 | + /// | ||
| 514 | + /// | ||
| 515 | + await AmapLocation.instance.updatePrivacyShow(true); | ||
| 516 | + await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 517 | + | ||
| 518 | + LatLng latLng = LatLng(latitude, longitude); | ||
| 519 | + ReGeocode reGeocodeList = await AmapSearch.instance.searchReGeocode(latLng); | ||
| 520 | + | ||
| 521 | + // print(await reGeocodeList.toFutureString()); | ||
| 522 | + address = reGeocodeList.formatAddress; | ||
| 523 | + | ||
| 524 | + await AmapLocation.instance.updatePrivacyShow(true); | ||
| 525 | + await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 526 | + inputTipDatas = await AmapSearch.instance.fetchInputTips( | ||
| 527 | + text, | ||
| 528 | + city: "", | ||
| 529 | + ); | ||
| 530 | + print(inputTipDatas); | ||
| 531 | + | ||
| 532 | + poiModel = new PoiModel("当前位置", address, latLng); | ||
| 533 | + list.clear(); | ||
| 534 | + list.add(poiModel); | ||
| 535 | + for (var inputTip in inputTipDatas) { | ||
| 536 | + String? title = await inputTip.name ?? ''; | ||
| 537 | + String? cityStr = | ||
| 538 | + await (inputTip.district ?? '') + (inputTip.address ?? ''); | ||
| 539 | + | ||
| 540 | + LatLng? latLng = await inputTip.coordinate; | ||
| 541 | + | ||
| 542 | + list.add(new PoiModel(title.toString(), cityStr, latLng)); | ||
| 543 | + } | ||
| 544 | + | ||
| 545 | + | ||
| 546 | + print(list); | ||
| 547 | + | ||
| 548 | + setState(() { | ||
| 549 | + // isloading = false; | ||
| 550 | + }); | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + void _loadData(LatLng latLng, {showloading = true}) async { | ||
| 554 | + flag = true; | ||
| 555 | + setState(() { | ||
| 556 | + if (showloading) { | ||
| 557 | + isloading = true; | ||
| 558 | + } | ||
| 559 | + }); | ||
| 560 | + | ||
| 561 | + /// 逆地理编码(坐标转地址) | ||
| 562 | + /// | ||
| 563 | + /// | ||
| 564 | + | ||
| 565 | + await AmapLocation.instance.updatePrivacyShow(true); | ||
| 566 | + await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 567 | + if (page == 1) { | ||
| 568 | + ReGeocode reGeocodeList = await AmapSearch.instance.searchReGeocode( | ||
| 569 | + latLng, | ||
| 570 | + ); | ||
| 571 | + // print(await reGeocodeList.toFutureString()); | ||
| 572 | + address = reGeocodeList.formatAddress; | ||
| 573 | + poiModel = new PoiModel("当前位置", address, latLng); | ||
| 574 | + list.clear(); | ||
| 575 | + list.add(poiModel); | ||
| 576 | + } | ||
| 577 | + final poiList = | ||
| 578 | + await AmapSearch.instance.searchAround(latLng, city: "", page: page); | ||
| 579 | + | ||
| 580 | + for (var poi in poiList) { | ||
| 581 | + String? title = await poi.title; | ||
| 582 | + String? cityName = await poi.cityName; | ||
| 583 | + String? provinceName = await poi.provinceName; | ||
| 584 | + String? address = await poi.address; | ||
| 585 | + LatLng? latLng = await poi.latLng; | ||
| 586 | + String? bussniss = poi.businessArea; | ||
| 587 | + | ||
| 588 | + list.add(new PoiModel( | ||
| 589 | + title.toString(), | ||
| 590 | + provinceName.toString() + | ||
| 591 | + cityName.toString() + | ||
| 592 | + address.toString() + | ||
| 593 | + bussniss.toString(), | ||
| 594 | + latLng)); | ||
| 595 | + } | ||
| 596 | + | ||
| 597 | + setState(() { | ||
| 598 | + if (showloading) { | ||
| 599 | + isloading = false; | ||
| 600 | + } | ||
| 601 | + }); | ||
| 602 | + } | ||
| 603 | + | ||
| 604 | + // void searchPoiId(String text) async { | ||
| 605 | + // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 606 | + // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 607 | + // Poi? poi = await AmapSearch.instance.searchPoiId( | ||
| 608 | + // text, | ||
| 609 | + // ); | ||
| 610 | + // print(poi); | ||
| 611 | + // } | ||
| 612 | + | ||
| 613 | + // void searchAroundAddress(String text) async { | ||
| 614 | + // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 615 | + // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 616 | + // final poiList = await AmapSearch.instance.searchKeyword( | ||
| 617 | + // text, | ||
| 618 | + // city: "", | ||
| 619 | + // ); | ||
| 620 | + // // final poiList = await AmapSearch.instance.searchAround( | ||
| 621 | + // // LatLng(latitude, longitude), | ||
| 622 | + // // city: "", | ||
| 623 | + // // radius: 100000000000000 | ||
| 624 | + | ||
| 625 | + // // ); | ||
| 626 | + | ||
| 627 | + // list.clear(); | ||
| 628 | + // list.add(poiModel); | ||
| 629 | + // for (var poi in poiList) { | ||
| 630 | + // String? title = await poi.title; | ||
| 631 | + // LatLng? latLng = await poi.latLng; | ||
| 632 | + // String? cityName = await poi.cityName; | ||
| 633 | + // String? provinceName = await poi.provinceName; | ||
| 634 | + // String? address = await poi.address; | ||
| 635 | + // list.add(new PoiModel( | ||
| 636 | + // title.toString(), | ||
| 637 | + // provinceName.toString() + cityName.toString() + address.toString(), | ||
| 638 | + // latLng)); | ||
| 639 | + // } | ||
| 640 | + // setState(() { | ||
| 641 | + // isloading = false; | ||
| 642 | + // FocusScope.of(context).requestFocus(FocusNode()); | ||
| 643 | + // }); | ||
| 644 | + // } | ||
| 645 | +} | ||
| 646 | + | ||
| 647 | +class PoiModel { | ||
| 648 | + LatLng? latLng; | ||
| 649 | + String title; | ||
| 650 | + String? address; | ||
| 651 | + | ||
| 652 | + PoiModel(this.title, this.address, this.latLng); | ||
| 653 | +} |
| 1 | -import 'dart:async'; | ||
| 2 | -// import 'dart:js_interop'; | 1 | +// import 'dart:async'; |
| 2 | +// // import 'dart:js_interop'; | ||
| 3 | 3 | ||
| 4 | -import 'package:flutter/material.dart'; | 4 | +// import 'package:flutter/material.dart'; |
| 5 | 5 | ||
| 6 | -import 'package:csp_amap_flutter_map/csp_amap_flutter_map.dart'; | ||
| 7 | -import 'package:csp_amap_flutter_location/amap_flutter_location.dart'; | ||
| 8 | -import 'package:csp_amap_flutter_location/amap_location_option.dart'; | ||
| 9 | -import 'package:flutter/cupertino.dart'; | 6 | +// import 'package:csp_amap_flutter_map/csp_amap_flutter_map.dart'; |
| 7 | +// import 'package:csp_amap_flutter_location/amap_flutter_location.dart'; | ||
| 8 | +// import 'package:csp_amap_flutter_location/amap_location_option.dart'; | ||
| 9 | +// import 'package:flutter/cupertino.dart'; | ||
| 10 | 10 | ||
| 11 | -// import 'package:flutter/material.dart'; | 11 | +// // import 'package:flutter/material.dart'; |
| 12 | 12 | ||
| 13 | -import 'package:csp_amap_flutter_base/csp_amap_flutter_base.dart'; | 13 | +// import 'package:csp_amap_flutter_base/csp_amap_flutter_base.dart'; |
| 14 | 14 | ||
| 15 | -import 'package:flutter_easyrefresh/easy_refresh.dart'; | ||
| 16 | - | ||
| 17 | -import 'package:one_key/pages/create_store/const_config.dart'; | ||
| 18 | -import 'package:one_key/pages/create_store/map_inputs_model.dart'; | ||
| 19 | - | ||
| 20 | -import 'package:one_key/res/colors.dart'; | ||
| 21 | -import 'package:one_key/utils/common_utils.dart'; | ||
| 22 | - | ||
| 23 | -import 'package:one_key/utils/misc.dart'; | ||
| 24 | - | ||
| 25 | -import 'package:one_key/utils/screen_util.dart'; | ||
| 26 | -import 'package:one_key/utils/utils.dart'; | ||
| 27 | - | ||
| 28 | -import 'package:one_key/widgets/system_app_bar.dart'; | ||
| 29 | -import 'package:permission_handler/permission_handler.dart'; | ||
| 30 | - | ||
| 31 | -// import '../../utils/common_utils.dart'; | ||
| 32 | -// import 'package:demo/resources/custom_text_style.dart'; | ||
| 33 | -// import 'package:demo/utils/misc.dart'; | ||
| 34 | - | ||
| 35 | -// import 'package:demo/widgets/network_state/page_loading.dart'; | ||
| 36 | - | ||
| 37 | -class MapChoicePointPage extends StatefulWidget { | ||
| 38 | - final String? long; | ||
| 39 | - final String? lat; | ||
| 40 | - MapChoicePointPage({Key? key, this.long, this.lat}) : super(key: key); | ||
| 41 | - | ||
| 42 | - @override | ||
| 43 | - _MapChoicePointPageState createState() => _MapChoicePointPageState(); | ||
| 44 | -} | ||
| 45 | - | ||
| 46 | -class _MapChoicePointPageState extends State<MapChoicePointPage> { | ||
| 47 | - late AMapController _mapController; | ||
| 48 | - final double _minZoom = 3; | ||
| 49 | - final double _maxZoom = 20; | ||
| 50 | - String? _currentZoom; | ||
| 51 | - // List<Poi>? poiList; | ||
| 52 | - static List<PoiModel?> list = []; | ||
| 53 | - static List<PoiModel> searchlist = []; | ||
| 54 | - PoiModel? poiModel; | ||
| 55 | - String keyword = ""; | ||
| 56 | - String? address = ""; | ||
| 57 | - bool isloading = true; | ||
| 58 | - | ||
| 59 | - double latitude = 39.684670899; | ||
| 60 | - double longitude = 118.17630045; | ||
| 61 | - | ||
| 62 | - double latitudeLocation = 39.684670899; | ||
| 63 | - double longitudeLocation = 118.17630045; | ||
| 64 | - | ||
| 65 | - List<MapInputsModel> inputTipDatas = []; | ||
| 66 | - int page = 1; | ||
| 67 | - EasyRefreshController refreshController = EasyRefreshController(); | ||
| 68 | - bool flag = true; | ||
| 69 | - | ||
| 70 | - /// 存储定位结果 | ||
| 71 | - Map<String, Object>? _locationResult; | ||
| 72 | - | ||
| 73 | - /// 定位结果监听器 | ||
| 74 | - StreamSubscription<Map<String, Object>>? _locationListener; | ||
| 75 | - | ||
| 76 | - /// 地理位置解析结果监听器 | ||
| 77 | - StreamSubscription<Map<String, Object>>? _geocodeSearchListener; | ||
| 78 | - | ||
| 79 | - /// 高德定位插件实例 | ||
| 80 | - final AMapFlutterLocation _locationPlugin = new AMapFlutterLocation(); | ||
| 81 | - | ||
| 82 | - @override | ||
| 83 | - void initState() { | ||
| 84 | - super.initState(); | ||
| 85 | - | ||
| 86 | - if (widget.long != null && widget.long != '' && widget.long != 'null') { | ||
| 87 | - longitude = double.parse(widget.long!); | ||
| 88 | - } | ||
| 89 | - if (widget.lat != null && widget.lat != '' && widget.lat != 'null') { | ||
| 90 | - latitude = double.parse(widget.lat!); | ||
| 91 | - } | ||
| 92 | - | ||
| 93 | - WidgetsBinding.instance.addPostFrameCallback((_) async { | ||
| 94 | - AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys); | ||
| 95 | - AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement); | ||
| 96 | - | ||
| 97 | - AMapFlutterLocation.setApiKey("1dbf56e2e8a4d0e4cdc2df9efd36bc71", | ||
| 98 | - "dfb64c0463cb53927914364b5c09aba0", | ||
| 99 | - ohosKey: "7c2081e92ec65bfffa2df0a5464f0c7b"); | ||
| 100 | - | ||
| 101 | - /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作 | ||
| 102 | - /// | ||
| 103 | - /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 104 | - /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b> | ||
| 105 | - /// | ||
| 106 | - /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 107 | - /// | ||
| 108 | - /// [hasContains] 隐私声明中是否包含高德隐私政策说明 | ||
| 109 | - /// | ||
| 110 | - /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 111 | - AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 112 | - | ||
| 113 | - /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作 | ||
| 114 | - /// | ||
| 115 | - /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 116 | - /// | ||
| 117 | - /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b> | ||
| 118 | - /// | ||
| 119 | - /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 120 | - AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 121 | - _requestLocationPermission(); | ||
| 122 | - | ||
| 123 | - // ama | ||
| 124 | - // let marker = new AMap.Marker({//添加标记点 | ||
| 125 | - // position: this.position, | ||
| 126 | - // map: map | ||
| 127 | - }); | ||
| 128 | - | ||
| 129 | - _geocodeSearchListener = _locationPlugin | ||
| 130 | - .onGeocodeSearchChange() | ||
| 131 | - .listen((Map<String, Object> result) { | ||
| 132 | - // setState(() { | ||
| 133 | - | ||
| 134 | - if (result.containsKey('errorCode')) { | ||
| 135 | - Utils.showToast(result['errorInfo'].toString()); | ||
| 136 | - } else { | ||
| 137 | - _locationResult = result; | ||
| 138 | - | ||
| 139 | - print(_locationResult); | ||
| 140 | - } | ||
| 141 | - }); | ||
| 142 | - | ||
| 143 | - /// 注册定位结果监听 | ||
| 144 | - /// 通过监听器接收定位结果并更新UI | ||
| 145 | - _locationListener = _locationPlugin | ||
| 146 | - .onLocationChanged() | ||
| 147 | - .listen((Map<String, Object> result) { | ||
| 148 | - // setState(() { | ||
| 149 | - | ||
| 150 | - if (result.containsKey('errorCode')) { | ||
| 151 | - Utils.showToast(result['errorInfo'].toString()); | ||
| 152 | - } else { | ||
| 153 | - _locationResult = result; | ||
| 154 | - | ||
| 155 | - print(_locationResult); | ||
| 156 | - | ||
| 157 | - if (result['latitude'] == null || result['latitude'] == '') //网络不好,定位失败 | ||
| 158 | - { | ||
| 159 | - // App.sp.setString("lat", "39.684670899"); | ||
| 160 | - // App.sp.setString("lng", "118.17630045"); | ||
| 161 | - } else { | ||
| 162 | - if (widget.long == null || | ||
| 163 | - widget.long == '' || | ||
| 164 | - widget.long == 'null') { | ||
| 165 | - latitude = double.parse(result['latitude'].toString()); | ||
| 166 | - longitude = double.parse(result['longitude'].toString()); | ||
| 167 | - // if (_mapController != null) { | ||
| 168 | - _mapController.moveCamera( | ||
| 169 | - CameraUpdate.newLatLng(LatLng(latitude, longitude))); | ||
| 170 | - | ||
| 171 | - // } | ||
| 172 | - page = 1; | ||
| 173 | - | ||
| 174 | - // _loadData(LatLng(latitude, longitude)); | ||
| 175 | - | ||
| 176 | - // setState(() {}); | ||
| 177 | - } | ||
| 178 | - latitudeLocation = latitude; | ||
| 179 | - longitudeLocation = longitude; | ||
| 180 | - _mapController.moveCamera( | ||
| 181 | - CameraUpdate.newLatLng(LatLng(latitudeLocation, longitudeLocation)), | ||
| 182 | - animated: true, | ||
| 183 | - ); | ||
| 184 | - _loadData(LatLng(latitude, longitude)); | ||
| 185 | - } | ||
| 186 | - } | ||
| 187 | - }); | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | - @override | ||
| 191 | - void dispose() { | ||
| 192 | - super.dispose(); | ||
| 193 | - | ||
| 194 | - /// 移除定位监听 | ||
| 195 | - /// 防止内存泄漏 | ||
| 196 | - if (null != _locationListener) { | ||
| 197 | - _locationListener?.cancel(); | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - if (null != _geocodeSearchListener) { | ||
| 201 | - _geocodeSearchListener?.cancel(); | ||
| 202 | - } | ||
| 203 | - | ||
| 204 | - /// 销毁定位 | ||
| 205 | - /// 释放定位资源 | ||
| 206 | - _locationPlugin.destroy(); | ||
| 207 | - } | ||
| 208 | - | ||
| 209 | - // Future<bool> checkLocationPermission() async { | ||
| 210 | - // PermissionStatus permissionStatus = await Permission.location.status; | ||
| 211 | - // if (permissionStatus == PermissionStatus.granted) { | ||
| 212 | - // return true; | ||
| 213 | - // } else { | ||
| 214 | - // return false; | ||
| 215 | - // } | ||
| 216 | - // } | ||
| 217 | - | ||
| 218 | - /// 检查权限并定 | ||
| 219 | - // _getLocationPermission() async { | ||
| 220 | - // if (!(await checkPermission(Permission.location))) { | ||
| 221 | - // //没有定位权限 | ||
| 222 | - | ||
| 223 | - // //申请定位权限 | ||
| 224 | - // _requestLocationPermission(); | ||
| 225 | - // } else { | ||
| 226 | - // //去定位 | ||
| 227 | - // _requestLocationPermission(); | ||
| 228 | - // } | ||
| 229 | - // } | ||
| 230 | - | ||
| 231 | - /// 设置定位参数 | ||
| 232 | - /// 配置定位选项,如精度、频率等 | ||
| 233 | - void _setLocationOption() { | ||
| 234 | - AMapLocationOption locationOption = new AMapLocationOption(); | ||
| 235 | - | ||
| 236 | - /// 是否单次定位 | ||
| 237 | - /// false表示连续定位 | ||
| 238 | - locationOption.onceLocation = true; | ||
| 239 | - | ||
| 240 | - /// 是否需要返回逆地理信息 | ||
| 241 | - /// true表示需要返回地址信息 | ||
| 242 | - locationOption.needAddress = true; | ||
| 243 | - | ||
| 244 | - /// 是否需要返回逆地理编码信息 | ||
| 245 | - locationOption.locatingWithReGeocode = true; | ||
| 246 | - | ||
| 247 | - /// 逆地理信息的语言类型 | ||
| 248 | - /// 默认为自动适配当前系统语言 | ||
| 249 | - locationOption.geoLanguage = GeoLanguage.DEFAULT; | ||
| 250 | - | ||
| 251 | - /// iOS 14定位精度权限设置 | ||
| 252 | - /// 设置为模糊定位精度 | ||
| 253 | - locationOption.desiredLocationAccuracyAuthorizationMode = | ||
| 254 | - AMapLocationAccuracyAuthorizationMode.ReduceAccuracy; | ||
| 255 | - | ||
| 256 | - /// iOS 14精确定位目的key | ||
| 257 | - /// 需要与info.plist中配置一致 | ||
| 258 | - locationOption.fullAccuracyPurposeKey = "AMapLocationScene"; | ||
| 259 | - | ||
| 260 | - /// 设置Android端连续定位的定位间隔 | ||
| 261 | - /// 单位:毫秒 | ||
| 262 | - locationOption.locationInterval = 2000; | ||
| 263 | - | ||
| 264 | - /// 设置Android端的定位模式 | ||
| 265 | - /// 可选值: | ||
| 266 | - /// [AMapLocationMode.Battery_Saving] 低功耗模式 | ||
| 267 | - /// [AMapLocationMode.Device_Sensors] 仅设备模式 | ||
| 268 | - /// [AMapLocationMode.Hight_Accuracy] 高精度模式 | ||
| 269 | - locationOption.locationMode = AMapLocationMode.Hight_Accuracy; | ||
| 270 | - | ||
| 271 | - /// 设置iOS端的定位最小更新距离 | ||
| 272 | - /// -1表示不限制距离 | ||
| 273 | - locationOption.distanceFilter = -1; | ||
| 274 | - | ||
| 275 | - /// 设置iOS端期望的定位精度 | ||
| 276 | - /// 可选值: | ||
| 277 | - /// [DesiredAccuracy.Best] 最高精度 | ||
| 278 | - /// [DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 | ||
| 279 | - /// [DesiredAccuracy.NearestTenMeters] 10米 | ||
| 280 | - /// [DesiredAccuracy.Kilometer] 1000米 | ||
| 281 | - /// [DesiredAccuracy.ThreeKilometers] 3000米 | ||
| 282 | - locationOption.desiredAccuracy = DesiredAccuracy.Best; | ||
| 283 | - | ||
| 284 | - /// 设置iOS端是否允许系统暂停定位 | ||
| 285 | - /// false表示不允许系统暂停定位 | ||
| 286 | - locationOption.pausesLocationUpdatesAutomatically = false; | ||
| 287 | - | ||
| 288 | - /// 将定位参数设置给定位插件 | ||
| 289 | - _locationPlugin.setLocationOption(locationOption); | ||
| 290 | - } | ||
| 291 | - | ||
| 292 | - /// 获取定位权限 | ||
| 293 | - _requestLocationPermission() async { | ||
| 294 | - /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 295 | - AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 296 | - | ||
| 297 | - /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 298 | - AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 299 | - // await AMapFlutterLocation.instance.updatePrivacyShow(true); | ||
| 300 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 301 | - bool canLocation = false; | ||
| 302 | - | ||
| 303 | - if (!(await checkPermission(Permission.location))) { | ||
| 304 | - //没有定位权限 | ||
| 305 | - | ||
| 306 | - //申请定位权限 | ||
| 307 | - canLocation = await requestPermission(Permission.location); | ||
| 308 | - } else { | ||
| 309 | - canLocation = true; | ||
| 310 | - } | ||
| 311 | - // bool canLocation = await requestPermission(Permission.location); | ||
| 312 | - // 单次定位 | ||
| 313 | - if (canLocation) { | ||
| 314 | - Future.delayed(Duration(milliseconds: 200), () async { | ||
| 315 | - /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 316 | - AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 317 | - | ||
| 318 | - /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 319 | - AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 320 | - _startLocation(); | ||
| 321 | - // final location = await AmapLocation.instance.fetchLocation( | ||
| 322 | - // // needAddress: true, | ||
| 323 | - // // mode: LocationAccuracy.High, | ||
| 324 | - // // timeout: Duration(seconds: 10) | ||
| 325 | - // ); | ||
| 326 | - | ||
| 327 | - // if (location.city == null || location.city == '') //网络不好,定位失败 | ||
| 328 | - // { | ||
| 329 | - // // App.sp.setString("lat", "39.684670899"); | ||
| 330 | - // // App.sp.setString("lng", "118.17630045"); | ||
| 331 | - // } else { | ||
| 332 | - // if (widget.long == null || | ||
| 333 | - // widget.long == '' || | ||
| 334 | - // widget.long == 'null') { | ||
| 335 | - // latitude = location.latLng!.latitude; | ||
| 336 | - // longitude = location.latLng!.longitude; | ||
| 337 | - // if (_controller != null) { | ||
| 338 | - // _controller!.setCenterCoordinate(LatLng( | ||
| 339 | - // location.latLng!.latitude, location.latLng!.longitude)); | ||
| 340 | - // } | ||
| 341 | - | ||
| 342 | - // page = 1; | ||
| 343 | - | ||
| 344 | - // _loadData( | ||
| 345 | - // LatLng(location.latLng!.latitude, location.latLng!.longitude)); | ||
| 346 | - | ||
| 347 | - // setState(() {}); | ||
| 348 | - // } | ||
| 349 | - // latitudeLocation = location.latLng!.latitude; | ||
| 350 | - // longitudeLocation = location.latLng!.longitude; | ||
| 351 | - // } | ||
| 352 | - }); | ||
| 353 | - } else { | ||
| 354 | - //无权限 | ||
| 355 | - } | ||
| 356 | - } | ||
| 357 | - | ||
| 358 | - // 开始定位 | ||
| 359 | - /// 设置定位参数并启动定位 | ||
| 360 | - void _startLocation() { | ||
| 361 | - /// 开始定位之前设置定位参数 | ||
| 362 | - _setLocationOption(); | ||
| 363 | - _locationPlugin.startLocation(); | ||
| 364 | - } | ||
| 365 | - | ||
| 366 | - /// 停止定位 | ||
| 367 | - /// 停止定位服务 | ||
| 368 | - void _stopLocation() { | ||
| 369 | - _locationPlugin.stopLocation(); | ||
| 370 | - } | ||
| 371 | - | ||
| 372 | - void onMapCreated(AMapController controller) { | ||
| 373 | - // setState(() { | ||
| 374 | - _mapController = controller; | ||
| 375 | - // _mapController.moveCamera( | ||
| 376 | - // CameraUpdate.newLatLng(LatLng(latitudeLocation, longitudeLocation)), | ||
| 377 | - // animated: true, | ||
| 378 | - // ); | ||
| 379 | - // getApprovalNumber(); | ||
| 380 | - // }); | ||
| 381 | - } | ||
| 382 | - | ||
| 383 | - /// 获取审图号 | ||
| 384 | - // void getApprovalNumber() async { | ||
| 385 | - // //普通地图审图号 | ||
| 386 | - // String mapContentApprovalNumber = | ||
| 387 | - // (await _mapController.getMapContentApprovalNumber()); | ||
| 388 | - // //卫星地图审图号 | ||
| 389 | - // String satelliteImageApprovalNumber = | ||
| 390 | - // (await _mapController.getSatelliteImageApprovalNumber()); | ||
| 391 | - | ||
| 392 | - // print('地图审图号(普通地图): $mapContentApprovalNumber'); | ||
| 393 | - // print('地图审图号(卫星地图): $satelliteImageApprovalNumber'); | ||
| 394 | - // } | ||
| 395 | - | ||
| 396 | - //移动视野 | ||
| 397 | - // void _onCameraMove(CameraPosition cameraPosition) { | ||
| 398 | - // latitude = cameraPosition.target.latitude; | ||
| 399 | - // longitude = cameraPosition.target.longitude; | ||
| 400 | - // page = 1; | ||
| 401 | - // _loadData(cameraPosition.target); | ||
| 402 | - // } | ||
| 403 | - | ||
| 404 | - //移动地图结束 | ||
| 405 | - void _onCameraMoveEnd(CameraPosition cameraPosition) { | ||
| 406 | - setState(() { | ||
| 407 | - _currentZoom = '当前缩放级别:${cameraPosition.zoom}'; | ||
| 408 | - }); | ||
| 409 | - | ||
| 410 | - _mapController.moveCamera( | ||
| 411 | - CameraUpdate.zoomTo(cameraPosition.zoom), | ||
| 412 | - animated: true, | ||
| 413 | - ); | ||
| 414 | - latitude = cameraPosition.target.latitude; | ||
| 415 | - longitude = cameraPosition.target.longitude; | ||
| 416 | - page = 1; | ||
| 417 | - _loadData(cameraPosition.target); | ||
| 418 | - } | ||
| 419 | - | ||
| 420 | - @override | ||
| 421 | - Widget build(BuildContext context) { | ||
| 422 | - final AMapWidget amap = AMapWidget( | ||
| 423 | - initialCameraPosition: | ||
| 424 | - CameraPosition(target: LatLng(latitude, longitude), zoom: 16), | ||
| 425 | - onMapCreated: onMapCreated, | ||
| 426 | - // onCameraMove: _onCameraMove, | ||
| 427 | - onCameraMoveEnd: _onCameraMoveEnd, | ||
| 428 | - minMaxZoomPreference: MinMaxZoomPreference(_minZoom, _maxZoom), | ||
| 429 | - scaleEnabled: true, | ||
| 430 | - ); | ||
| 431 | - | ||
| 432 | - return Scaffold( | ||
| 433 | - resizeToAvoidBottomInset: false, //防止底部布局被顶起 | ||
| 434 | - appBar: SystemAppBar( | ||
| 435 | - '选择位置信息', | ||
| 436 | - onTap: () { | ||
| 437 | - if (Navigator.canPop(context)) { | ||
| 438 | - Navigator.pop(context); | ||
| 439 | - } | ||
| 440 | - }, | ||
| 441 | - ), | ||
| 442 | - | ||
| 443 | - body: Column( | ||
| 444 | - children: <Widget>[ | ||
| 445 | - // Theme( | ||
| 446 | - // data: new | ||
| 447 | - // ThemeData( | ||
| 448 | - // // primaryColor: MyColours.color_438E93, | ||
| 449 | - // // hintColor: MyColours.color_438E93), | ||
| 450 | - // child: | ||
| 451 | - // Container( | ||
| 452 | - // color: MyColours.color_438E93, | ||
| 453 | - // decoration: BoxDecoration( | ||
| 454 | - // color: MyColours.color_438E93, | ||
| 455 | - // boxShadow: [ | ||
| 456 | - // BoxShadow(color: Colors.white, spreadRadius: 1), | ||
| 457 | - // ], | ||
| 458 | - // ), | ||
| 459 | - | ||
| 460 | - // padding: EdgeInsets.all(5), | ||
| 461 | - // child: | ||
| 462 | - | ||
| 463 | - // ), | ||
| 464 | - // ), | ||
| 465 | - // ListView.builder( | ||
| 466 | - // shrinkWrap: true, | ||
| 467 | - // itemCount: inputTipDatas.length, | ||
| 468 | - // itemBuilder: (context, index) { | ||
| 469 | - // InputTip inputTip = inputTipDatas[index]; | ||
| 470 | - // return InkWell( | ||
| 471 | - // onTap: () { | ||
| 472 | - // // searchAroundAddress(inputTip.name ?? ''); | ||
| 473 | - // // searchPoiId(inputTip.poiId ?? ''); | ||
| 474 | - // // _loadData(inputTip.coordinate ?? | ||
| 475 | - // // LatLng(latitude, longitude)); | ||
| 476 | - // }, | ||
| 477 | - // child: Container( | ||
| 478 | - // child: Row( | ||
| 479 | - // children: [ | ||
| 480 | - // Text( | ||
| 481 | - // inputTip.name ?? '', | ||
| 482 | - // style: TextStyle( | ||
| 483 | - // fontSize: font(15), | ||
| 484 | - // color: MyColours.color_515151), | ||
| 485 | - // ), | ||
| 486 | - // HEmptyView(10), | ||
| 487 | - // Expanded( | ||
| 488 | - // child: Text( | ||
| 489 | - // (inputTip.district ?? '') + | ||
| 490 | - // (inputTip.address ?? ''), | ||
| 491 | - // style: TextStyle( | ||
| 492 | - // fontSize: font(13), | ||
| 493 | - // color: MyColours.color_999999), | ||
| 494 | - // ), | ||
| 495 | - // ), | ||
| 496 | - // ], | ||
| 497 | - // ))); | ||
| 498 | - // }) | ||
| 499 | - // ], | ||
| 500 | - // ), | ||
| 501 | - | ||
| 502 | - Stack( | ||
| 503 | - children: [ | ||
| 504 | - Container( | ||
| 505 | - height: w(300), | ||
| 506 | - child: Stack( | ||
| 507 | - children: <Widget>[ | ||
| 508 | - amap, | ||
| 509 | - // AmapView( | ||
| 510 | - // showZoomControl: false, | ||
| 511 | - | ||
| 512 | - // /// 是否显示指南针控件 | ||
| 513 | - // showCompass: true, | ||
| 514 | - | ||
| 515 | - // /// 是否显示比例尺控件 | ||
| 516 | - // showScaleControl: true, | ||
| 517 | - | ||
| 518 | - // /// 是否使能缩放手势 | ||
| 519 | - // zoomGesturesEnabled: true, | ||
| 520 | - | ||
| 521 | - // /// 是否使能滚动手势 | ||
| 522 | - // scrollGesturesEnabled: true, | ||
| 523 | - | ||
| 524 | - // /// 是否使能旋转手势 | ||
| 525 | - // rotateGestureEnabled: false, | ||
| 526 | - // centerCoordinate: LatLng(latitude, longitude), | ||
| 527 | - // maskDelay: Duration(milliseconds: 500), | ||
| 528 | - // zoomLevel: 19, | ||
| 529 | - // onMapCreated: (controller) async { | ||
| 530 | - // _controller = controller; | ||
| 531 | - // _controller! | ||
| 532 | - // .setCenterCoordinate(LatLng(latitude, longitude)); | ||
| 533 | - // // if (await requestPermission(PermissionGroup.location)) { | ||
| 534 | - // // await controller.showMyLocation(true); | ||
| 535 | - // // await controller?.showLocateControl(true); | ||
| 536 | - // // final latLng = await _controller?.getLocation( | ||
| 537 | - // // delay: Duration(seconds: 2)); | ||
| 538 | - // // await enableFluttifyLog(false); // 关闭log | ||
| 539 | - // // _loadData(latLng); | ||
| 540 | - // // } else { | ||
| 541 | - // // //无权限 | ||
| 542 | - // // _showLocPemWidget(); | ||
| 543 | - // // } | ||
| 544 | - // }, | ||
| 545 | - // // markers: [], | ||
| 546 | - // onMapMoveEnd: (MapMove move) async { | ||
| 547 | - // latitude = move.coordinate!.latitude; | ||
| 548 | - // longitude = move.coordinate!.longitude; | ||
| 549 | - // page = 1; | ||
| 550 | - // _loadData(move.coordinate!); | ||
| 551 | - // }, | ||
| 552 | - // ), | ||
| 553 | - Center( | ||
| 554 | - child: Icon( | ||
| 555 | - Icons.place, | ||
| 556 | - size: w(32), | ||
| 557 | - color: Color(0xFFFF0000), | ||
| 558 | - ), | ||
| 559 | - ), | ||
| 560 | - Positioned( | ||
| 561 | - right: w(10), | ||
| 562 | - bottom: w(10), | ||
| 563 | - child: InkWell( | ||
| 564 | - onTap: () { | ||
| 565 | - _mapController.moveCamera( | ||
| 566 | - CameraUpdate.newLatLng( | ||
| 567 | - LatLng(latitudeLocation, longitudeLocation)), | ||
| 568 | - animated: true, | ||
| 569 | - ); | ||
| 570 | - }, | ||
| 571 | - child: Container( | ||
| 572 | - decoration: BoxDecoration( | ||
| 573 | - color: MyColours.color_ffffff, | ||
| 574 | - borderRadius: BorderRadius.circular(r(5))), | ||
| 575 | - padding: EdgeInsets.all(w(5)), | ||
| 576 | - child: Image.asset( | ||
| 577 | - Utils.getImgPath('location_map'), | ||
| 578 | - width: w(25), | ||
| 579 | - ), | ||
| 580 | - )), | ||
| 581 | - ) | ||
| 582 | - ], | ||
| 583 | - ), | ||
| 584 | - ), | ||
| 585 | - Positioned( | ||
| 586 | - top: w(10), | ||
| 587 | - left: w(20), | ||
| 588 | - right: w(20), | ||
| 589 | - child: Container( | ||
| 590 | - // height: w(45), | ||
| 591 | - padding: EdgeInsets.symmetric(vertical: w(10)), | ||
| 592 | - decoration: BoxDecoration( | ||
| 593 | - color: Colors.white, | ||
| 594 | - borderRadius: BorderRadius.circular(r(10))), | ||
| 595 | - child: TextField( | ||
| 596 | - textAlignVertical: TextAlignVertical.center, | ||
| 597 | - style: TextStyle( | ||
| 598 | - color: MyColours.color_515151, | ||
| 599 | - fontSize: font(15), | ||
| 600 | - ), | ||
| 601 | - controller: | ||
| 602 | - TextEditingController.fromValue(TextEditingValue( | ||
| 603 | - // 设置内容 | ||
| 604 | - text: keyword, | ||
| 605 | - selection: TextSelection.fromPosition(TextPosition( | ||
| 606 | - affinity: TextAffinity.downstream, | ||
| 607 | - offset: keyword.length)), | ||
| 608 | - // 保持光标在最后 | ||
| 609 | - )), | ||
| 610 | - decoration: InputDecoration( | ||
| 611 | - // border: b, | ||
| 612 | - // border: OutlineInputBorder( | ||
| 613 | - // borderRadius: BorderRadius.all(Radius.circular(40)), | ||
| 614 | - // ), | ||
| 615 | - border: OutlineInputBorder(borderSide: BorderSide.none), | ||
| 616 | - hintText: '输入关键字', | ||
| 617 | - isCollapsed: true, | ||
| 618 | - | ||
| 619 | - hintStyle: TextStyle( | ||
| 620 | - color: MyColours.color_999999, fontSize: font(15)), | ||
| 621 | - // contentPadding: const EdgeInsets.symmetric( | ||
| 622 | - // vertical: 8, horizontal: 1), | ||
| 623 | - prefixIconConstraints: BoxConstraints(maxWidth: w(40)), | ||
| 624 | - prefixIcon: Padding( | ||
| 625 | - padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 626 | - child: SizedBox( | ||
| 627 | - width: w(30), | ||
| 628 | - child: Image.asset( | ||
| 629 | - Utils.getImgPath('search_black'), | ||
| 630 | - ))), | ||
| 631 | - suffixIconConstraints: BoxConstraints(maxWidth: w(32)), | ||
| 632 | - suffixIcon: InkWell( | ||
| 633 | - child: Padding( | ||
| 634 | - padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 635 | - child: SizedBox( | ||
| 636 | - width: w(22), | ||
| 637 | - child: Image.asset( | ||
| 638 | - Utils.getImgPath('delete_black'), | ||
| 639 | - ))), | ||
| 640 | - onTap: () { | ||
| 641 | - keyword = ""; | ||
| 642 | - setState(() {}); | ||
| 643 | - }, | ||
| 644 | - ), | ||
| 645 | - fillColor: Colors.white, | ||
| 646 | - filled: true, | ||
| 647 | - ), | ||
| 648 | - | ||
| 649 | - inputFormatters: [], | ||
| 650 | - //内容改变的回调 | ||
| 651 | - onChanged: (text) { | ||
| 652 | - print('change $text'); | ||
| 653 | - keyword = text; | ||
| 654 | - | ||
| 655 | - //搜索 | ||
| 656 | - | ||
| 657 | - if (text != null && text.trim().length > 0) { | ||
| 658 | - JhCommonUtils.debounce( | ||
| 659 | - () => _fetchInputTips(text.toString())); | ||
| 660 | - } | ||
| 661 | - }, | ||
| 662 | - //内容提交(按回车)的回调 | ||
| 663 | - onSubmitted: (text) { | ||
| 664 | - print('submit $text'); | ||
| 665 | - // 触发关闭弹出来的键盘。 | ||
| 666 | - keyword = text; | ||
| 667 | - FocusScope.of(context).requestFocus(FocusNode()); | ||
| 668 | - setState(() { | ||
| 669 | - // isloading = true; | ||
| 670 | - }); | ||
| 671 | - | ||
| 672 | - // _fetchInputTips(text.toString()); | ||
| 673 | - | ||
| 674 | - // searchAroundAddress(text.toString()); | ||
| 675 | - }, | ||
| 676 | - //按回车时调用 | ||
| 677 | - onEditingComplete: () { | ||
| 678 | - print('onEditingComplete'); | ||
| 679 | - }, | ||
| 680 | - ), | ||
| 681 | - ), | ||
| 682 | - ) | ||
| 683 | - ], | ||
| 684 | - ), | ||
| 685 | - | ||
| 686 | - Expanded( | ||
| 687 | - flex: 1, | ||
| 688 | - child: Visibility( | ||
| 689 | - visible: !isloading, | ||
| 690 | - maintainSize: false, | ||
| 691 | - maintainSemantics: false, | ||
| 692 | - maintainInteractivity: false, | ||
| 693 | - replacement: Center( | ||
| 694 | - child: CupertinoActivityIndicator(), | ||
| 695 | - ), | ||
| 696 | - child: EasyRefresh.custom( | ||
| 697 | - controller: refreshController, | ||
| 698 | - slivers: [ | ||
| 699 | - SliverList( | ||
| 700 | - delegate: SliverChildBuilderDelegate( | ||
| 701 | - (BuildContext context, int position) { | ||
| 702 | - print("itemBuilder" + list.length.toString()); | ||
| 703 | - PoiModel item = list[position]!; | ||
| 704 | - return InkWell( | ||
| 705 | - child: Column( | ||
| 706 | - children: <Widget>[ | ||
| 707 | - Container( | ||
| 708 | - margin: EdgeInsets.only( | ||
| 709 | - top: 8, bottom: 5, left: 10), | ||
| 710 | - child: Row( | ||
| 711 | - children: <Widget>[ | ||
| 712 | - Icon( | ||
| 713 | - Icons.place, | ||
| 714 | - size: 20.0, | ||
| 715 | - color: position == 0 | ||
| 716 | - ? Colors.green | ||
| 717 | - : Colors.grey, | ||
| 718 | - ), | ||
| 719 | - Expanded( | ||
| 720 | - child: Text(item.title, | ||
| 721 | - style: TextStyle( | ||
| 722 | - fontSize: 16, | ||
| 723 | - color: position == 0 | ||
| 724 | - ? Colors.green | ||
| 725 | - : Color(0xFF787878)))) | ||
| 726 | - ], | ||
| 727 | - ), | ||
| 728 | - ), | ||
| 729 | - Container( | ||
| 730 | - margin: EdgeInsets.only( | ||
| 731 | - top: 5, bottom: 5, left: 18), | ||
| 732 | - alignment: Alignment.centerLeft, | ||
| 733 | - child: Text( | ||
| 734 | - item.address!, | ||
| 735 | - style: TextStyle( | ||
| 736 | - fontSize: 14, | ||
| 737 | - color: Color(0xFF646464), | ||
| 738 | - ), | ||
| 739 | - ), | ||
| 740 | - ), | ||
| 741 | - Divider( | ||
| 742 | - height: 1, | ||
| 743 | - ) | ||
| 744 | - ], | ||
| 745 | - ), | ||
| 746 | - onTap: () async { | ||
| 747 | - // await _controller.setCenterCoordinate( | ||
| 748 | - // LatLng(item.latLng.latitude, item.latLng.longitude), | ||
| 749 | - // zoomLevel: 16); | ||
| 750 | - if (Navigator.canPop(context)) { | ||
| 751 | - Navigator.pop(context, { | ||
| 752 | - 'address': item.address, | ||
| 753 | - 'lat': item.latLng!.latitude.toString(), | ||
| 754 | - 'lng': item.latLng!.longitude.toString() | ||
| 755 | - }); | ||
| 756 | - } | ||
| 757 | - }, | ||
| 758 | - ); | ||
| 759 | - }, | ||
| 760 | - childCount: list.length, | ||
| 761 | - ), | ||
| 762 | - ) | ||
| 763 | - ], | ||
| 764 | - onRefresh: () async { | ||
| 765 | - if (flag) { | ||
| 766 | - page = 1; | ||
| 767 | - _loadData(LatLng(latitude, longitude)); | ||
| 768 | - } | ||
| 769 | - }, | ||
| 770 | - onLoad: () async { | ||
| 771 | - if (flag) { | ||
| 772 | - page++; | ||
| 773 | - _loadData(LatLng(latitude, longitude), | ||
| 774 | - showloading: false); | ||
| 775 | - } | ||
| 776 | - }, | ||
| 777 | - )), | ||
| 778 | - ), | ||
| 779 | - ], | ||
| 780 | - ), | ||
| 781 | - ); | ||
| 782 | - } | ||
| 783 | - | ||
| 784 | - _fetchInputTips(String text) async { | ||
| 785 | - flag = false; | ||
| 786 | - page = 1; | ||
| 787 | - // setState(() { | ||
| 788 | - // isloading = true; | ||
| 789 | - // }); | ||
| 790 | - | ||
| 791 | - /// 逆地理编码(坐标转地址) | ||
| 792 | - /// | ||
| 793 | - /// | ||
| 794 | - // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 795 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 796 | - | ||
| 797 | - LatLng latLng = LatLng(latitude, longitude); | ||
| 798 | - | ||
| 799 | - address = await _locationPlugin | ||
| 800 | - .onGeocodeSearch(true, [latLng.longitude, latLng.latitude]); | ||
| 801 | - | ||
| 802 | - // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 803 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 804 | - | ||
| 805 | - List<dynamic> temp = await _locationPlugin.doInputtipsRequest( | ||
| 806 | - text, | ||
| 807 | - city: "", | ||
| 808 | - ); | ||
| 809 | - | ||
| 810 | - inputTipDatas = []; | ||
| 811 | - | ||
| 812 | - temp.forEach((element) { | ||
| 813 | - inputTipDatas.add(MapInputsModel.fromJson(element)); | ||
| 814 | - }); | ||
| 815 | - | ||
| 816 | - print(inputTipDatas); | ||
| 817 | - poiModel = new PoiModel("当前位置", address, latLng); | ||
| 818 | - list.clear(); | ||
| 819 | - list.add(poiModel); | ||
| 820 | - for (var inputTip in inputTipDatas) { | ||
| 821 | - String? title = await inputTip.name ?? ''; | ||
| 822 | - String? cityStr = (inputTip.district ?? '') + (inputTip.city ?? ''); | ||
| 823 | - | ||
| 824 | - // LatLng? latLng = await inputTip.point; | ||
| 825 | - | ||
| 826 | - list.add(new PoiModel(title.toString(), cityStr, latLng)); | ||
| 827 | - } | ||
| 828 | - | ||
| 829 | - print(list); | ||
| 830 | - | ||
| 831 | - setState(() { | ||
| 832 | - // isloading = false; | ||
| 833 | - }); | ||
| 834 | - } | ||
| 835 | - | ||
| 836 | - void _loadData(LatLng latLng, {showloading = true}) async { | ||
| 837 | - flag = true; | ||
| 838 | - setState(() { | ||
| 839 | - if (showloading) { | ||
| 840 | - isloading = true; | ||
| 841 | - } | ||
| 842 | - }); | ||
| 843 | - | ||
| 844 | - /// 逆地理编码(坐标转地址) | ||
| 845 | - /// | ||
| 846 | - /// | ||
| 847 | - /// | ||
| 848 | - | ||
| 849 | - // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 850 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 851 | - if (page == 1) { | ||
| 852 | - address = await _locationPlugin | ||
| 853 | - .onGeocodeSearch(true, [latLng.longitude, latLng.latitude]); | ||
| 854 | - poiModel = new PoiModel("当前位置", address, latLng); | ||
| 855 | - list.clear(); | ||
| 856 | - list.add(poiModel); | ||
| 857 | - } | ||
| 858 | - // final poiList | ||
| 859 | - List<dynamic> temp = await _locationPlugin.poiSearchAround( | ||
| 860 | - keyword, latLng.longitude, latLng.latitude); | ||
| 861 | - | ||
| 862 | - List<MapRoundSearchModel> searchData = []; | ||
| 863 | - | ||
| 864 | - temp.forEach((element) { | ||
| 865 | - searchData.add(MapRoundSearchModel.fromJson(element)); | ||
| 866 | - }); | ||
| 867 | - | ||
| 868 | - print(searchData); | ||
| 869 | - | ||
| 870 | - for (var poi in searchData) { | ||
| 871 | - String? title = await poi.title; | ||
| 872 | - String? cityName = await poi.cityName; | ||
| 873 | - String? provinceName = await poi.provinceName; | ||
| 874 | - String? snippet = await poi.snippet; | ||
| 875 | - String? adName = await poi.adName; | ||
| 876 | - LatLng? latLng = LatLng(poi.latitude ?? 0, poi.longitude ?? 0); | ||
| 877 | - String? bussniss = poi.businessArea; | ||
| 878 | - | ||
| 879 | - list.add(new PoiModel( | ||
| 880 | - title.toString(), | ||
| 881 | - provinceName.toString() + | ||
| 882 | - cityName.toString() + | ||
| 883 | - adName.toString() + | ||
| 884 | - // address.toString() + | ||
| 885 | - bussniss.toString() + | ||
| 886 | - snippet.toString(), | ||
| 887 | - latLng)); | ||
| 888 | - } | ||
| 889 | - | ||
| 890 | - setState(() { | ||
| 891 | - if (showloading) { | ||
| 892 | - isloading = false; | ||
| 893 | - } | ||
| 894 | - }); | ||
| 895 | - } | ||
| 896 | - | ||
| 897 | - // void searchPoiId(String text) async { | ||
| 898 | - // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 899 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 900 | - // Poi? poi = await AmapSearch.instance.searchPoiId( | ||
| 901 | - // text, | ||
| 902 | - // ); | ||
| 903 | - // print(poi); | ||
| 904 | - // } | ||
| 905 | - | ||
| 906 | - // void searchAroundAddress(String text) async { | ||
| 907 | - // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 908 | - // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 909 | - // final poiList = await AmapSearch.instance.searchKeyword( | ||
| 910 | - // text, | ||
| 911 | - // city: "", | ||
| 912 | - // ); | ||
| 913 | - // // final poiList = await AmapSearch.instance.searchAround( | ||
| 914 | - // // LatLng(latitude, longitude), | ||
| 915 | - // // city: "", | ||
| 916 | - // // radius: 100000000000000 | ||
| 917 | - | ||
| 918 | - // // ); | ||
| 919 | - | ||
| 920 | - // list.clear(); | ||
| 921 | - // list.add(poiModel); | ||
| 922 | - // for (var poi in poiList) { | ||
| 923 | - // String? title = await poi.title; | ||
| 924 | - // LatLng? latLng = await poi.latLng; | ||
| 925 | - // String? cityName = await poi.cityName; | ||
| 926 | - // String? provinceName = await poi.provinceName; | ||
| 927 | - // String? address = await poi.address; | ||
| 928 | - // list.add(new PoiModel( | ||
| 929 | - // title.toString(), | ||
| 930 | - // provinceName.toString() + cityName.toString() + address.toString(), | ||
| 931 | - // latLng)); | ||
| 932 | - // } | ||
| 933 | - // setState(() { | ||
| 934 | - // isloading = false; | ||
| 935 | - // FocusScope.of(context).requestFocus(FocusNode()); | ||
| 936 | - // }); | ||
| 937 | - // } | ||
| 938 | -} | ||
| 939 | - | ||
| 940 | -class PoiModel { | ||
| 941 | - LatLng? latLng; | ||
| 942 | - String title; | ||
| 943 | - String? address; | ||
| 944 | - | ||
| 945 | - PoiModel(this.title, this.address, this.latLng); | ||
| 946 | -} | 15 | +// import 'package:flutter_easyrefresh/easy_refresh.dart'; |
| 16 | + | ||
| 17 | +// import 'package:one_key/pages/create_store/const_config.dart'; | ||
| 18 | +// import 'package:one_key/pages/create_store/map_inputs_model.dart'; | ||
| 19 | + | ||
| 20 | +// import 'package:one_key/res/colors.dart'; | ||
| 21 | +// import 'package:one_key/utils/common_utils.dart'; | ||
| 22 | + | ||
| 23 | +// import 'package:one_key/utils/misc.dart'; | ||
| 24 | + | ||
| 25 | +// import 'package:one_key/utils/screen_util.dart'; | ||
| 26 | +// import 'package:one_key/utils/utils.dart'; | ||
| 27 | + | ||
| 28 | +// import 'package:one_key/widgets/system_app_bar.dart'; | ||
| 29 | +// import 'package:permission_handler/permission_handler.dart'; | ||
| 30 | + | ||
| 31 | +// // import '../../utils/common_utils.dart'; | ||
| 32 | +// // import 'package:demo/resources/custom_text_style.dart'; | ||
| 33 | +// // import 'package:demo/utils/misc.dart'; | ||
| 34 | + | ||
| 35 | +// // import 'package:demo/widgets/network_state/page_loading.dart'; | ||
| 36 | + | ||
| 37 | +// class MapChoicePointPage extends StatefulWidget { | ||
| 38 | +// final String? long; | ||
| 39 | +// final String? lat; | ||
| 40 | +// MapChoicePointPage({Key? key, this.long, this.lat}) : super(key: key); | ||
| 41 | + | ||
| 42 | +// @override | ||
| 43 | +// _MapChoicePointPageState createState() => _MapChoicePointPageState(); | ||
| 44 | +// } | ||
| 45 | + | ||
| 46 | +// class _MapChoicePointPageState extends State<MapChoicePointPage> { | ||
| 47 | +// late AMapController _mapController; | ||
| 48 | +// final double _minZoom = 3; | ||
| 49 | +// final double _maxZoom = 20; | ||
| 50 | +// String? _currentZoom; | ||
| 51 | +// // List<Poi>? poiList; | ||
| 52 | +// static List<PoiModel?> list = []; | ||
| 53 | +// static List<PoiModel> searchlist = []; | ||
| 54 | +// PoiModel? poiModel; | ||
| 55 | +// String keyword = ""; | ||
| 56 | +// String? address = ""; | ||
| 57 | +// bool isloading = true; | ||
| 58 | + | ||
| 59 | +// double latitude = 39.684670899; | ||
| 60 | +// double longitude = 118.17630045; | ||
| 61 | + | ||
| 62 | +// double latitudeLocation = 39.684670899; | ||
| 63 | +// double longitudeLocation = 118.17630045; | ||
| 64 | + | ||
| 65 | +// List<MapInputsModel> inputTipDatas = []; | ||
| 66 | +// int page = 1; | ||
| 67 | +// EasyRefreshController refreshController = EasyRefreshController(); | ||
| 68 | +// bool flag = true; | ||
| 69 | + | ||
| 70 | +// /// 存储定位结果 | ||
| 71 | +// Map<String, Object>? _locationResult; | ||
| 72 | + | ||
| 73 | +// /// 定位结果监听器 | ||
| 74 | +// StreamSubscription<Map<String, Object>>? _locationListener; | ||
| 75 | + | ||
| 76 | +// /// 地理位置解析结果监听器 | ||
| 77 | +// StreamSubscription<Map<String, Object>>? _geocodeSearchListener; | ||
| 78 | + | ||
| 79 | +// /// 高德定位插件实例 | ||
| 80 | +// final AMapFlutterLocation _locationPlugin = new AMapFlutterLocation(); | ||
| 81 | + | ||
| 82 | +// @override | ||
| 83 | +// void initState() { | ||
| 84 | +// super.initState(); | ||
| 85 | + | ||
| 86 | +// if (widget.long != null && widget.long != '' && widget.long != 'null') { | ||
| 87 | +// longitude = double.parse(widget.long!); | ||
| 88 | +// } | ||
| 89 | +// if (widget.lat != null && widget.lat != '' && widget.lat != 'null') { | ||
| 90 | +// latitude = double.parse(widget.lat!); | ||
| 91 | +// } | ||
| 92 | + | ||
| 93 | +// WidgetsBinding.instance.addPostFrameCallback((_) async { | ||
| 94 | +// AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys); | ||
| 95 | +// AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement); | ||
| 96 | + | ||
| 97 | +// AMapFlutterLocation.setApiKey("1dbf56e2e8a4d0e4cdc2df9efd36bc71", | ||
| 98 | +// "dfb64c0463cb53927914364b5c09aba0", | ||
| 99 | +// ohosKey: "7c2081e92ec65bfffa2df0a5464f0c7b"); | ||
| 100 | + | ||
| 101 | +// /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作 | ||
| 102 | +// /// | ||
| 103 | +// /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 104 | +// /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b> | ||
| 105 | +// /// | ||
| 106 | +// /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 107 | +// /// | ||
| 108 | +// /// [hasContains] 隐私声明中是否包含高德隐私政策说明 | ||
| 109 | +// /// | ||
| 110 | +// /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 111 | +// AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 112 | + | ||
| 113 | +// /// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作 | ||
| 114 | +// /// | ||
| 115 | +// /// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy | ||
| 116 | +// /// | ||
| 117 | +// /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b> | ||
| 118 | +// /// | ||
| 119 | +// /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 120 | +// AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 121 | +// _requestLocationPermission(); | ||
| 122 | + | ||
| 123 | +// // ama | ||
| 124 | +// // let marker = new AMap.Marker({//添加标记点 | ||
| 125 | +// // position: this.position, | ||
| 126 | +// // map: map | ||
| 127 | +// }); | ||
| 128 | + | ||
| 129 | +// _geocodeSearchListener = _locationPlugin | ||
| 130 | +// .onGeocodeSearchChange() | ||
| 131 | +// .listen((Map<String, Object> result) { | ||
| 132 | +// // setState(() { | ||
| 133 | + | ||
| 134 | +// if (result.containsKey('errorCode')) { | ||
| 135 | +// Utils.showToast(result['errorInfo'].toString()); | ||
| 136 | +// } else { | ||
| 137 | +// _locationResult = result; | ||
| 138 | + | ||
| 139 | +// print(_locationResult); | ||
| 140 | +// } | ||
| 141 | +// }); | ||
| 142 | + | ||
| 143 | +// /// 注册定位结果监听 | ||
| 144 | +// /// 通过监听器接收定位结果并更新UI | ||
| 145 | +// _locationListener = _locationPlugin | ||
| 146 | +// .onLocationChanged() | ||
| 147 | +// .listen((Map<String, Object> result) { | ||
| 148 | +// // setState(() { | ||
| 149 | + | ||
| 150 | +// if (result.containsKey('errorCode')) { | ||
| 151 | +// Utils.showToast(result['errorInfo'].toString()); | ||
| 152 | +// } else { | ||
| 153 | +// _locationResult = result; | ||
| 154 | + | ||
| 155 | +// print(_locationResult); | ||
| 156 | + | ||
| 157 | +// if (result['latitude'] == null || result['latitude'] == '') //网络不好,定位失败 | ||
| 158 | +// { | ||
| 159 | +// // App.sp.setString("lat", "39.684670899"); | ||
| 160 | +// // App.sp.setString("lng", "118.17630045"); | ||
| 161 | +// } else { | ||
| 162 | +// if (widget.long == null || | ||
| 163 | +// widget.long == '' || | ||
| 164 | +// widget.long == 'null') { | ||
| 165 | +// latitude = double.parse(result['latitude'].toString()); | ||
| 166 | +// longitude = double.parse(result['longitude'].toString()); | ||
| 167 | +// // if (_mapController != null) { | ||
| 168 | +// _mapController.moveCamera( | ||
| 169 | +// CameraUpdate.newLatLng(LatLng(latitude, longitude))); | ||
| 170 | + | ||
| 171 | +// // } | ||
| 172 | +// page = 1; | ||
| 173 | + | ||
| 174 | +// // _loadData(LatLng(latitude, longitude)); | ||
| 175 | + | ||
| 176 | +// // setState(() {}); | ||
| 177 | +// } | ||
| 178 | +// latitudeLocation = latitude; | ||
| 179 | +// longitudeLocation = longitude; | ||
| 180 | +// _mapController.moveCamera( | ||
| 181 | +// CameraUpdate.newLatLng(LatLng(latitudeLocation, longitudeLocation)), | ||
| 182 | +// animated: true, | ||
| 183 | +// ); | ||
| 184 | +// _loadData(LatLng(latitude, longitude)); | ||
| 185 | +// } | ||
| 186 | +// } | ||
| 187 | +// }); | ||
| 188 | +// } | ||
| 189 | + | ||
| 190 | +// @override | ||
| 191 | +// void dispose() { | ||
| 192 | +// super.dispose(); | ||
| 193 | + | ||
| 194 | +// /// 移除定位监听 | ||
| 195 | +// /// 防止内存泄漏 | ||
| 196 | +// if (null != _locationListener) { | ||
| 197 | +// _locationListener?.cancel(); | ||
| 198 | +// } | ||
| 199 | + | ||
| 200 | +// if (null != _geocodeSearchListener) { | ||
| 201 | +// _geocodeSearchListener?.cancel(); | ||
| 202 | +// } | ||
| 203 | + | ||
| 204 | +// /// 销毁定位 | ||
| 205 | +// /// 释放定位资源 | ||
| 206 | +// _locationPlugin.destroy(); | ||
| 207 | +// } | ||
| 208 | + | ||
| 209 | +// // Future<bool> checkLocationPermission() async { | ||
| 210 | +// // PermissionStatus permissionStatus = await Permission.location.status; | ||
| 211 | +// // if (permissionStatus == PermissionStatus.granted) { | ||
| 212 | +// // return true; | ||
| 213 | +// // } else { | ||
| 214 | +// // return false; | ||
| 215 | +// // } | ||
| 216 | +// // } | ||
| 217 | + | ||
| 218 | +// /// 检查权限并定 | ||
| 219 | +// // _getLocationPermission() async { | ||
| 220 | +// // if (!(await checkPermission(Permission.location))) { | ||
| 221 | +// // //没有定位权限 | ||
| 222 | + | ||
| 223 | +// // //申请定位权限 | ||
| 224 | +// // _requestLocationPermission(); | ||
| 225 | +// // } else { | ||
| 226 | +// // //去定位 | ||
| 227 | +// // _requestLocationPermission(); | ||
| 228 | +// // } | ||
| 229 | +// // } | ||
| 230 | + | ||
| 231 | +// /// 设置定位参数 | ||
| 232 | +// /// 配置定位选项,如精度、频率等 | ||
| 233 | +// void _setLocationOption() { | ||
| 234 | +// AMapLocationOption locationOption = new AMapLocationOption(); | ||
| 235 | + | ||
| 236 | +// /// 是否单次定位 | ||
| 237 | +// /// false表示连续定位 | ||
| 238 | +// locationOption.onceLocation = true; | ||
| 239 | + | ||
| 240 | +// /// 是否需要返回逆地理信息 | ||
| 241 | +// /// true表示需要返回地址信息 | ||
| 242 | +// locationOption.needAddress = true; | ||
| 243 | + | ||
| 244 | +// /// 是否需要返回逆地理编码信息 | ||
| 245 | +// locationOption.locatingWithReGeocode = true; | ||
| 246 | + | ||
| 247 | +// /// 逆地理信息的语言类型 | ||
| 248 | +// /// 默认为自动适配当前系统语言 | ||
| 249 | +// locationOption.geoLanguage = GeoLanguage.DEFAULT; | ||
| 250 | + | ||
| 251 | +// /// iOS 14定位精度权限设置 | ||
| 252 | +// /// 设置为模糊定位精度 | ||
| 253 | +// locationOption.desiredLocationAccuracyAuthorizationMode = | ||
| 254 | +// AMapLocationAccuracyAuthorizationMode.ReduceAccuracy; | ||
| 255 | + | ||
| 256 | +// /// iOS 14精确定位目的key | ||
| 257 | +// /// 需要与info.plist中配置一致 | ||
| 258 | +// locationOption.fullAccuracyPurposeKey = "AMapLocationScene"; | ||
| 259 | + | ||
| 260 | +// /// 设置Android端连续定位的定位间隔 | ||
| 261 | +// /// 单位:毫秒 | ||
| 262 | +// locationOption.locationInterval = 2000; | ||
| 263 | + | ||
| 264 | +// /// 设置Android端的定位模式 | ||
| 265 | +// /// 可选值: | ||
| 266 | +// /// [AMapLocationMode.Battery_Saving] 低功耗模式 | ||
| 267 | +// /// [AMapLocationMode.Device_Sensors] 仅设备模式 | ||
| 268 | +// /// [AMapLocationMode.Hight_Accuracy] 高精度模式 | ||
| 269 | +// locationOption.locationMode = AMapLocationMode.Hight_Accuracy; | ||
| 270 | + | ||
| 271 | +// /// 设置iOS端的定位最小更新距离 | ||
| 272 | +// /// -1表示不限制距离 | ||
| 273 | +// locationOption.distanceFilter = -1; | ||
| 274 | + | ||
| 275 | +// /// 设置iOS端期望的定位精度 | ||
| 276 | +// /// 可选值: | ||
| 277 | +// /// [DesiredAccuracy.Best] 最高精度 | ||
| 278 | +// /// [DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 | ||
| 279 | +// /// [DesiredAccuracy.NearestTenMeters] 10米 | ||
| 280 | +// /// [DesiredAccuracy.Kilometer] 1000米 | ||
| 281 | +// /// [DesiredAccuracy.ThreeKilometers] 3000米 | ||
| 282 | +// locationOption.desiredAccuracy = DesiredAccuracy.Best; | ||
| 283 | + | ||
| 284 | +// /// 设置iOS端是否允许系统暂停定位 | ||
| 285 | +// /// false表示不允许系统暂停定位 | ||
| 286 | +// locationOption.pausesLocationUpdatesAutomatically = false; | ||
| 287 | + | ||
| 288 | +// /// 将定位参数设置给定位插件 | ||
| 289 | +// _locationPlugin.setLocationOption(locationOption); | ||
| 290 | +// } | ||
| 291 | + | ||
| 292 | +// /// 获取定位权限 | ||
| 293 | +// _requestLocationPermission() async { | ||
| 294 | +// /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 295 | +// AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 296 | + | ||
| 297 | +// /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 298 | +// AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 299 | +// // await AMapFlutterLocation.instance.updatePrivacyShow(true); | ||
| 300 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 301 | +// bool canLocation = false; | ||
| 302 | + | ||
| 303 | +// if (!(await checkPermission(Permission.location))) { | ||
| 304 | +// //没有定位权限 | ||
| 305 | + | ||
| 306 | +// //申请定位权限 | ||
| 307 | +// canLocation = await requestPermission(Permission.location); | ||
| 308 | +// } else { | ||
| 309 | +// canLocation = true; | ||
| 310 | +// } | ||
| 311 | +// // bool canLocation = await requestPermission(Permission.location); | ||
| 312 | +// // 单次定位 | ||
| 313 | +// if (canLocation) { | ||
| 314 | +// Future.delayed(Duration(milliseconds: 200), () async { | ||
| 315 | +// /// [hasShow] 隐私权政策是否弹窗展示告知用户 | ||
| 316 | +// AMapFlutterLocation.updatePrivacyShow(true, true); | ||
| 317 | + | ||
| 318 | +// /// [hasAgree] 隐私权政策是否已经取得用户同意 | ||
| 319 | +// AMapFlutterLocation.updatePrivacyAgree(true); | ||
| 320 | +// _startLocation(); | ||
| 321 | +// // final location = await AmapLocation.instance.fetchLocation( | ||
| 322 | +// // // needAddress: true, | ||
| 323 | +// // // mode: LocationAccuracy.High, | ||
| 324 | +// // // timeout: Duration(seconds: 10) | ||
| 325 | +// // ); | ||
| 326 | + | ||
| 327 | +// // if (location.city == null || location.city == '') //网络不好,定位失败 | ||
| 328 | +// // { | ||
| 329 | +// // // App.sp.setString("lat", "39.684670899"); | ||
| 330 | +// // // App.sp.setString("lng", "118.17630045"); | ||
| 331 | +// // } else { | ||
| 332 | +// // if (widget.long == null || | ||
| 333 | +// // widget.long == '' || | ||
| 334 | +// // widget.long == 'null') { | ||
| 335 | +// // latitude = location.latLng!.latitude; | ||
| 336 | +// // longitude = location.latLng!.longitude; | ||
| 337 | +// // if (_controller != null) { | ||
| 338 | +// // _controller!.setCenterCoordinate(LatLng( | ||
| 339 | +// // location.latLng!.latitude, location.latLng!.longitude)); | ||
| 340 | +// // } | ||
| 341 | + | ||
| 342 | +// // page = 1; | ||
| 343 | + | ||
| 344 | +// // _loadData( | ||
| 345 | +// // LatLng(location.latLng!.latitude, location.latLng!.longitude)); | ||
| 346 | + | ||
| 347 | +// // setState(() {}); | ||
| 348 | +// // } | ||
| 349 | +// // latitudeLocation = location.latLng!.latitude; | ||
| 350 | +// // longitudeLocation = location.latLng!.longitude; | ||
| 351 | +// // } | ||
| 352 | +// }); | ||
| 353 | +// } else { | ||
| 354 | +// //无权限 | ||
| 355 | +// } | ||
| 356 | +// } | ||
| 357 | + | ||
| 358 | +// // 开始定位 | ||
| 359 | +// /// 设置定位参数并启动定位 | ||
| 360 | +// void _startLocation() { | ||
| 361 | +// /// 开始定位之前设置定位参数 | ||
| 362 | +// _setLocationOption(); | ||
| 363 | +// _locationPlugin.startLocation(); | ||
| 364 | +// } | ||
| 365 | + | ||
| 366 | +// /// 停止定位 | ||
| 367 | +// /// 停止定位服务 | ||
| 368 | +// void _stopLocation() { | ||
| 369 | +// _locationPlugin.stopLocation(); | ||
| 370 | +// } | ||
| 371 | + | ||
| 372 | +// void onMapCreated(AMapController controller) { | ||
| 373 | +// // setState(() { | ||
| 374 | +// _mapController = controller; | ||
| 375 | +// // _mapController.moveCamera( | ||
| 376 | +// // CameraUpdate.newLatLng(LatLng(latitudeLocation, longitudeLocation)), | ||
| 377 | +// // animated: true, | ||
| 378 | +// // ); | ||
| 379 | +// // getApprovalNumber(); | ||
| 380 | +// // }); | ||
| 381 | +// } | ||
| 382 | + | ||
| 383 | +// /// 获取审图号 | ||
| 384 | +// // void getApprovalNumber() async { | ||
| 385 | +// // //普通地图审图号 | ||
| 386 | +// // String mapContentApprovalNumber = | ||
| 387 | +// // (await _mapController.getMapContentApprovalNumber()); | ||
| 388 | +// // //卫星地图审图号 | ||
| 389 | +// // String satelliteImageApprovalNumber = | ||
| 390 | +// // (await _mapController.getSatelliteImageApprovalNumber()); | ||
| 391 | + | ||
| 392 | +// // print('地图审图号(普通地图): $mapContentApprovalNumber'); | ||
| 393 | +// // print('地图审图号(卫星地图): $satelliteImageApprovalNumber'); | ||
| 394 | +// // } | ||
| 395 | + | ||
| 396 | +// //移动视野 | ||
| 397 | +// // void _onCameraMove(CameraPosition cameraPosition) { | ||
| 398 | +// // latitude = cameraPosition.target.latitude; | ||
| 399 | +// // longitude = cameraPosition.target.longitude; | ||
| 400 | +// // page = 1; | ||
| 401 | +// // _loadData(cameraPosition.target); | ||
| 402 | +// // } | ||
| 403 | + | ||
| 404 | +// //移动地图结束 | ||
| 405 | +// void _onCameraMoveEnd(CameraPosition cameraPosition) { | ||
| 406 | +// setState(() { | ||
| 407 | +// _currentZoom = '当前缩放级别:${cameraPosition.zoom}'; | ||
| 408 | +// }); | ||
| 409 | + | ||
| 410 | +// _mapController.moveCamera( | ||
| 411 | +// CameraUpdate.zoomTo(cameraPosition.zoom), | ||
| 412 | +// animated: true, | ||
| 413 | +// ); | ||
| 414 | +// latitude = cameraPosition.target.latitude; | ||
| 415 | +// longitude = cameraPosition.target.longitude; | ||
| 416 | +// page = 1; | ||
| 417 | +// _loadData(cameraPosition.target); | ||
| 418 | +// } | ||
| 419 | + | ||
| 420 | +// @override | ||
| 421 | +// Widget build(BuildContext context) { | ||
| 422 | +// final AMapWidget amap = AMapWidget( | ||
| 423 | +// initialCameraPosition: | ||
| 424 | +// CameraPosition(target: LatLng(latitude, longitude), zoom: 16), | ||
| 425 | +// onMapCreated: onMapCreated, | ||
| 426 | +// // onCameraMove: _onCameraMove, | ||
| 427 | +// onCameraMoveEnd: _onCameraMoveEnd, | ||
| 428 | +// minMaxZoomPreference: MinMaxZoomPreference(_minZoom, _maxZoom), | ||
| 429 | +// scaleEnabled: true, | ||
| 430 | +// ); | ||
| 431 | + | ||
| 432 | +// return Scaffold( | ||
| 433 | +// resizeToAvoidBottomInset: false, //防止底部布局被顶起 | ||
| 434 | +// appBar: SystemAppBar( | ||
| 435 | +// '选择位置信息', | ||
| 436 | +// onTap: () { | ||
| 437 | +// if (Navigator.canPop(context)) { | ||
| 438 | +// Navigator.pop(context); | ||
| 439 | +// } | ||
| 440 | +// }, | ||
| 441 | +// ), | ||
| 442 | + | ||
| 443 | +// body: Column( | ||
| 444 | +// children: <Widget>[ | ||
| 445 | +// // Theme( | ||
| 446 | +// // data: new | ||
| 447 | +// // ThemeData( | ||
| 448 | +// // // primaryColor: MyColours.color_438E93, | ||
| 449 | +// // // hintColor: MyColours.color_438E93), | ||
| 450 | +// // child: | ||
| 451 | +// // Container( | ||
| 452 | +// // color: MyColours.color_438E93, | ||
| 453 | +// // decoration: BoxDecoration( | ||
| 454 | +// // color: MyColours.color_438E93, | ||
| 455 | +// // boxShadow: [ | ||
| 456 | +// // BoxShadow(color: Colors.white, spreadRadius: 1), | ||
| 457 | +// // ], | ||
| 458 | +// // ), | ||
| 459 | + | ||
| 460 | +// // padding: EdgeInsets.all(5), | ||
| 461 | +// // child: | ||
| 462 | + | ||
| 463 | +// // ), | ||
| 464 | +// // ), | ||
| 465 | +// // ListView.builder( | ||
| 466 | +// // shrinkWrap: true, | ||
| 467 | +// // itemCount: inputTipDatas.length, | ||
| 468 | +// // itemBuilder: (context, index) { | ||
| 469 | +// // InputTip inputTip = inputTipDatas[index]; | ||
| 470 | +// // return InkWell( | ||
| 471 | +// // onTap: () { | ||
| 472 | +// // // searchAroundAddress(inputTip.name ?? ''); | ||
| 473 | +// // // searchPoiId(inputTip.poiId ?? ''); | ||
| 474 | +// // // _loadData(inputTip.coordinate ?? | ||
| 475 | +// // // LatLng(latitude, longitude)); | ||
| 476 | +// // }, | ||
| 477 | +// // child: Container( | ||
| 478 | +// // child: Row( | ||
| 479 | +// // children: [ | ||
| 480 | +// // Text( | ||
| 481 | +// // inputTip.name ?? '', | ||
| 482 | +// // style: TextStyle( | ||
| 483 | +// // fontSize: font(15), | ||
| 484 | +// // color: MyColours.color_515151), | ||
| 485 | +// // ), | ||
| 486 | +// // HEmptyView(10), | ||
| 487 | +// // Expanded( | ||
| 488 | +// // child: Text( | ||
| 489 | +// // (inputTip.district ?? '') + | ||
| 490 | +// // (inputTip.address ?? ''), | ||
| 491 | +// // style: TextStyle( | ||
| 492 | +// // fontSize: font(13), | ||
| 493 | +// // color: MyColours.color_999999), | ||
| 494 | +// // ), | ||
| 495 | +// // ), | ||
| 496 | +// // ], | ||
| 497 | +// // ))); | ||
| 498 | +// // }) | ||
| 499 | +// // ], | ||
| 500 | +// // ), | ||
| 501 | + | ||
| 502 | +// Stack( | ||
| 503 | +// children: [ | ||
| 504 | +// Container( | ||
| 505 | +// height: w(300), | ||
| 506 | +// child: Stack( | ||
| 507 | +// children: <Widget>[ | ||
| 508 | +// amap, | ||
| 509 | +// // AmapView( | ||
| 510 | +// // showZoomControl: false, | ||
| 511 | + | ||
| 512 | +// // /// 是否显示指南针控件 | ||
| 513 | +// // showCompass: true, | ||
| 514 | + | ||
| 515 | +// // /// 是否显示比例尺控件 | ||
| 516 | +// // showScaleControl: true, | ||
| 517 | + | ||
| 518 | +// // /// 是否使能缩放手势 | ||
| 519 | +// // zoomGesturesEnabled: true, | ||
| 520 | + | ||
| 521 | +// // /// 是否使能滚动手势 | ||
| 522 | +// // scrollGesturesEnabled: true, | ||
| 523 | + | ||
| 524 | +// // /// 是否使能旋转手势 | ||
| 525 | +// // rotateGestureEnabled: false, | ||
| 526 | +// // centerCoordinate: LatLng(latitude, longitude), | ||
| 527 | +// // maskDelay: Duration(milliseconds: 500), | ||
| 528 | +// // zoomLevel: 19, | ||
| 529 | +// // onMapCreated: (controller) async { | ||
| 530 | +// // _controller = controller; | ||
| 531 | +// // _controller! | ||
| 532 | +// // .setCenterCoordinate(LatLng(latitude, longitude)); | ||
| 533 | +// // // if (await requestPermission(PermissionGroup.location)) { | ||
| 534 | +// // // await controller.showMyLocation(true); | ||
| 535 | +// // // await controller?.showLocateControl(true); | ||
| 536 | +// // // final latLng = await _controller?.getLocation( | ||
| 537 | +// // // delay: Duration(seconds: 2)); | ||
| 538 | +// // // await enableFluttifyLog(false); // 关闭log | ||
| 539 | +// // // _loadData(latLng); | ||
| 540 | +// // // } else { | ||
| 541 | +// // // //无权限 | ||
| 542 | +// // // _showLocPemWidget(); | ||
| 543 | +// // // } | ||
| 544 | +// // }, | ||
| 545 | +// // // markers: [], | ||
| 546 | +// // onMapMoveEnd: (MapMove move) async { | ||
| 547 | +// // latitude = move.coordinate!.latitude; | ||
| 548 | +// // longitude = move.coordinate!.longitude; | ||
| 549 | +// // page = 1; | ||
| 550 | +// // _loadData(move.coordinate!); | ||
| 551 | +// // }, | ||
| 552 | +// // ), | ||
| 553 | +// Center( | ||
| 554 | +// child: Icon( | ||
| 555 | +// Icons.place, | ||
| 556 | +// size: w(32), | ||
| 557 | +// color: Color(0xFFFF0000), | ||
| 558 | +// ), | ||
| 559 | +// ), | ||
| 560 | +// Positioned( | ||
| 561 | +// right: w(10), | ||
| 562 | +// bottom: w(10), | ||
| 563 | +// child: InkWell( | ||
| 564 | +// onTap: () { | ||
| 565 | +// _mapController.moveCamera( | ||
| 566 | +// CameraUpdate.newLatLng( | ||
| 567 | +// LatLng(latitudeLocation, longitudeLocation)), | ||
| 568 | +// animated: true, | ||
| 569 | +// ); | ||
| 570 | +// }, | ||
| 571 | +// child: Container( | ||
| 572 | +// decoration: BoxDecoration( | ||
| 573 | +// color: MyColours.color_ffffff, | ||
| 574 | +// borderRadius: BorderRadius.circular(r(5))), | ||
| 575 | +// padding: EdgeInsets.all(w(5)), | ||
| 576 | +// child: Image.asset( | ||
| 577 | +// Utils.getImgPath('location_map'), | ||
| 578 | +// width: w(25), | ||
| 579 | +// ), | ||
| 580 | +// )), | ||
| 581 | +// ) | ||
| 582 | +// ], | ||
| 583 | +// ), | ||
| 584 | +// ), | ||
| 585 | +// Positioned( | ||
| 586 | +// top: w(10), | ||
| 587 | +// left: w(20), | ||
| 588 | +// right: w(20), | ||
| 589 | +// child: Container( | ||
| 590 | +// // height: w(45), | ||
| 591 | +// padding: EdgeInsets.symmetric(vertical: w(10)), | ||
| 592 | +// decoration: BoxDecoration( | ||
| 593 | +// color: Colors.white, | ||
| 594 | +// borderRadius: BorderRadius.circular(r(10))), | ||
| 595 | +// child: TextField( | ||
| 596 | +// textAlignVertical: TextAlignVertical.center, | ||
| 597 | +// style: TextStyle( | ||
| 598 | +// color: MyColours.color_515151, | ||
| 599 | +// fontSize: font(15), | ||
| 600 | +// ), | ||
| 601 | +// controller: | ||
| 602 | +// TextEditingController.fromValue(TextEditingValue( | ||
| 603 | +// // 设置内容 | ||
| 604 | +// text: keyword, | ||
| 605 | +// selection: TextSelection.fromPosition(TextPosition( | ||
| 606 | +// affinity: TextAffinity.downstream, | ||
| 607 | +// offset: keyword.length)), | ||
| 608 | +// // 保持光标在最后 | ||
| 609 | +// )), | ||
| 610 | +// decoration: InputDecoration( | ||
| 611 | +// // border: b, | ||
| 612 | +// // border: OutlineInputBorder( | ||
| 613 | +// // borderRadius: BorderRadius.all(Radius.circular(40)), | ||
| 614 | +// // ), | ||
| 615 | +// border: OutlineInputBorder(borderSide: BorderSide.none), | ||
| 616 | +// hintText: '输入关键字', | ||
| 617 | +// isCollapsed: true, | ||
| 618 | + | ||
| 619 | +// hintStyle: TextStyle( | ||
| 620 | +// color: MyColours.color_999999, fontSize: font(15)), | ||
| 621 | +// // contentPadding: const EdgeInsets.symmetric( | ||
| 622 | +// // vertical: 8, horizontal: 1), | ||
| 623 | +// prefixIconConstraints: BoxConstraints(maxWidth: w(40)), | ||
| 624 | +// prefixIcon: Padding( | ||
| 625 | +// padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 626 | +// child: SizedBox( | ||
| 627 | +// width: w(30), | ||
| 628 | +// child: Image.asset( | ||
| 629 | +// Utils.getImgPath('search_black'), | ||
| 630 | +// ))), | ||
| 631 | +// suffixIconConstraints: BoxConstraints(maxWidth: w(32)), | ||
| 632 | +// suffixIcon: InkWell( | ||
| 633 | +// child: Padding( | ||
| 634 | +// padding: EdgeInsets.only(left: w(10), right: w(10)), | ||
| 635 | +// child: SizedBox( | ||
| 636 | +// width: w(22), | ||
| 637 | +// child: Image.asset( | ||
| 638 | +// Utils.getImgPath('delete_black'), | ||
| 639 | +// ))), | ||
| 640 | +// onTap: () { | ||
| 641 | +// keyword = ""; | ||
| 642 | +// setState(() {}); | ||
| 643 | +// }, | ||
| 644 | +// ), | ||
| 645 | +// fillColor: Colors.white, | ||
| 646 | +// filled: true, | ||
| 647 | +// ), | ||
| 648 | + | ||
| 649 | +// inputFormatters: [], | ||
| 650 | +// //内容改变的回调 | ||
| 651 | +// onChanged: (text) { | ||
| 652 | +// print('change $text'); | ||
| 653 | +// keyword = text; | ||
| 654 | + | ||
| 655 | +// //搜索 | ||
| 656 | + | ||
| 657 | +// if (text != null && text.trim().length > 0) { | ||
| 658 | +// JhCommonUtils.debounce( | ||
| 659 | +// () => _fetchInputTips(text.toString())); | ||
| 660 | +// } | ||
| 661 | +// }, | ||
| 662 | +// //内容提交(按回车)的回调 | ||
| 663 | +// onSubmitted: (text) { | ||
| 664 | +// print('submit $text'); | ||
| 665 | +// // 触发关闭弹出来的键盘。 | ||
| 666 | +// keyword = text; | ||
| 667 | +// FocusScope.of(context).requestFocus(FocusNode()); | ||
| 668 | +// setState(() { | ||
| 669 | +// // isloading = true; | ||
| 670 | +// }); | ||
| 671 | + | ||
| 672 | +// // _fetchInputTips(text.toString()); | ||
| 673 | + | ||
| 674 | +// // searchAroundAddress(text.toString()); | ||
| 675 | +// }, | ||
| 676 | +// //按回车时调用 | ||
| 677 | +// onEditingComplete: () { | ||
| 678 | +// print('onEditingComplete'); | ||
| 679 | +// }, | ||
| 680 | +// ), | ||
| 681 | +// ), | ||
| 682 | +// ) | ||
| 683 | +// ], | ||
| 684 | +// ), | ||
| 685 | + | ||
| 686 | +// Expanded( | ||
| 687 | +// flex: 1, | ||
| 688 | +// child: Visibility( | ||
| 689 | +// visible: !isloading, | ||
| 690 | +// maintainSize: false, | ||
| 691 | +// maintainSemantics: false, | ||
| 692 | +// maintainInteractivity: false, | ||
| 693 | +// replacement: Center( | ||
| 694 | +// child: CupertinoActivityIndicator(), | ||
| 695 | +// ), | ||
| 696 | +// child: EasyRefresh.custom( | ||
| 697 | +// controller: refreshController, | ||
| 698 | +// slivers: [ | ||
| 699 | +// SliverList( | ||
| 700 | +// delegate: SliverChildBuilderDelegate( | ||
| 701 | +// (BuildContext context, int position) { | ||
| 702 | +// print("itemBuilder" + list.length.toString()); | ||
| 703 | +// PoiModel item = list[position]!; | ||
| 704 | +// return InkWell( | ||
| 705 | +// child: Column( | ||
| 706 | +// children: <Widget>[ | ||
| 707 | +// Container( | ||
| 708 | +// margin: EdgeInsets.only( | ||
| 709 | +// top: 8, bottom: 5, left: 10), | ||
| 710 | +// child: Row( | ||
| 711 | +// children: <Widget>[ | ||
| 712 | +// Icon( | ||
| 713 | +// Icons.place, | ||
| 714 | +// size: 20.0, | ||
| 715 | +// color: position == 0 | ||
| 716 | +// ? Colors.green | ||
| 717 | +// : Colors.grey, | ||
| 718 | +// ), | ||
| 719 | +// Expanded( | ||
| 720 | +// child: Text(item.title, | ||
| 721 | +// style: TextStyle( | ||
| 722 | +// fontSize: 16, | ||
| 723 | +// color: position == 0 | ||
| 724 | +// ? Colors.green | ||
| 725 | +// : Color(0xFF787878)))) | ||
| 726 | +// ], | ||
| 727 | +// ), | ||
| 728 | +// ), | ||
| 729 | +// Container( | ||
| 730 | +// margin: EdgeInsets.only( | ||
| 731 | +// top: 5, bottom: 5, left: 18), | ||
| 732 | +// alignment: Alignment.centerLeft, | ||
| 733 | +// child: Text( | ||
| 734 | +// item.address!, | ||
| 735 | +// style: TextStyle( | ||
| 736 | +// fontSize: 14, | ||
| 737 | +// color: Color(0xFF646464), | ||
| 738 | +// ), | ||
| 739 | +// ), | ||
| 740 | +// ), | ||
| 741 | +// Divider( | ||
| 742 | +// height: 1, | ||
| 743 | +// ) | ||
| 744 | +// ], | ||
| 745 | +// ), | ||
| 746 | +// onTap: () async { | ||
| 747 | +// // await _controller.setCenterCoordinate( | ||
| 748 | +// // LatLng(item.latLng.latitude, item.latLng.longitude), | ||
| 749 | +// // zoomLevel: 16); | ||
| 750 | +// if (Navigator.canPop(context)) { | ||
| 751 | +// Navigator.pop(context, { | ||
| 752 | +// 'address': item.address, | ||
| 753 | +// 'lat': item.latLng!.latitude.toString(), | ||
| 754 | +// 'lng': item.latLng!.longitude.toString() | ||
| 755 | +// }); | ||
| 756 | +// } | ||
| 757 | +// }, | ||
| 758 | +// ); | ||
| 759 | +// }, | ||
| 760 | +// childCount: list.length, | ||
| 761 | +// ), | ||
| 762 | +// ) | ||
| 763 | +// ], | ||
| 764 | +// onRefresh: () async { | ||
| 765 | +// if (flag) { | ||
| 766 | +// page = 1; | ||
| 767 | +// _loadData(LatLng(latitude, longitude)); | ||
| 768 | +// } | ||
| 769 | +// }, | ||
| 770 | +// onLoad: () async { | ||
| 771 | +// if (flag) { | ||
| 772 | +// page++; | ||
| 773 | +// _loadData(LatLng(latitude, longitude), | ||
| 774 | +// showloading: false); | ||
| 775 | +// } | ||
| 776 | +// }, | ||
| 777 | +// )), | ||
| 778 | +// ), | ||
| 779 | +// ], | ||
| 780 | +// ), | ||
| 781 | +// ); | ||
| 782 | +// } | ||
| 783 | + | ||
| 784 | +// _fetchInputTips(String text) async { | ||
| 785 | +// flag = false; | ||
| 786 | +// page = 1; | ||
| 787 | +// // setState(() { | ||
| 788 | +// // isloading = true; | ||
| 789 | +// // }); | ||
| 790 | + | ||
| 791 | +// /// 逆地理编码(坐标转地址) | ||
| 792 | +// /// | ||
| 793 | +// /// | ||
| 794 | +// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 795 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 796 | + | ||
| 797 | +// LatLng latLng = LatLng(latitude, longitude); | ||
| 798 | + | ||
| 799 | +// address = await _locationPlugin | ||
| 800 | +// .onGeocodeSearch(true, [latLng.longitude, latLng.latitude]); | ||
| 801 | + | ||
| 802 | +// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 803 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 804 | + | ||
| 805 | +// List<dynamic> temp = await _locationPlugin.doInputtipsRequest( | ||
| 806 | +// text, | ||
| 807 | +// city: "", | ||
| 808 | +// ); | ||
| 809 | + | ||
| 810 | +// inputTipDatas = []; | ||
| 811 | + | ||
| 812 | +// temp.forEach((element) { | ||
| 813 | +// inputTipDatas.add(MapInputsModel.fromJson(element)); | ||
| 814 | +// }); | ||
| 815 | + | ||
| 816 | +// print(inputTipDatas); | ||
| 817 | +// poiModel = new PoiModel("当前位置", address, latLng); | ||
| 818 | +// list.clear(); | ||
| 819 | +// list.add(poiModel); | ||
| 820 | +// for (var inputTip in inputTipDatas) { | ||
| 821 | +// String? title = await inputTip.name ?? ''; | ||
| 822 | +// String? cityStr = (inputTip.district ?? '') + (inputTip.city ?? ''); | ||
| 823 | + | ||
| 824 | +// // LatLng? latLng = await inputTip.point; | ||
| 825 | + | ||
| 826 | +// list.add(new PoiModel(title.toString(), cityStr, latLng)); | ||
| 827 | +// } | ||
| 828 | + | ||
| 829 | +// print(list); | ||
| 830 | + | ||
| 831 | +// setState(() { | ||
| 832 | +// // isloading = false; | ||
| 833 | +// }); | ||
| 834 | +// } | ||
| 835 | + | ||
| 836 | +// void _loadData(LatLng latLng, {showloading = true}) async { | ||
| 837 | +// flag = true; | ||
| 838 | +// setState(() { | ||
| 839 | +// if (showloading) { | ||
| 840 | +// isloading = true; | ||
| 841 | +// } | ||
| 842 | +// }); | ||
| 843 | + | ||
| 844 | +// /// 逆地理编码(坐标转地址) | ||
| 845 | +// /// | ||
| 846 | +// /// | ||
| 847 | +// /// | ||
| 848 | + | ||
| 849 | +// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 850 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 851 | +// if (page == 1) { | ||
| 852 | +// address = await _locationPlugin | ||
| 853 | +// .onGeocodeSearch(true, [latLng.longitude, latLng.latitude]); | ||
| 854 | +// poiModel = new PoiModel("当前位置", address, latLng); | ||
| 855 | +// list.clear(); | ||
| 856 | +// list.add(poiModel); | ||
| 857 | +// } | ||
| 858 | +// // final poiList | ||
| 859 | +// List<dynamic> temp = await _locationPlugin.poiSearchAround( | ||
| 860 | +// keyword, latLng.longitude, latLng.latitude); | ||
| 861 | + | ||
| 862 | +// List<MapRoundSearchModel> searchData = []; | ||
| 863 | + | ||
| 864 | +// temp.forEach((element) { | ||
| 865 | +// searchData.add(MapRoundSearchModel.fromJson(element)); | ||
| 866 | +// }); | ||
| 867 | + | ||
| 868 | +// print(searchData); | ||
| 869 | + | ||
| 870 | +// for (var poi in searchData) { | ||
| 871 | +// String? title = await poi.title; | ||
| 872 | +// String? cityName = await poi.cityName; | ||
| 873 | +// String? provinceName = await poi.provinceName; | ||
| 874 | +// String? snippet = await poi.snippet; | ||
| 875 | +// String? adName = await poi.adName; | ||
| 876 | +// LatLng? latLng = LatLng(poi.latitude ?? 0, poi.longitude ?? 0); | ||
| 877 | +// String? bussniss = poi.businessArea; | ||
| 878 | + | ||
| 879 | +// list.add(new PoiModel( | ||
| 880 | +// title.toString(), | ||
| 881 | +// provinceName.toString() + | ||
| 882 | +// cityName.toString() + | ||
| 883 | +// adName.toString() + | ||
| 884 | +// // address.toString() + | ||
| 885 | +// bussniss.toString() + | ||
| 886 | +// snippet.toString(), | ||
| 887 | +// latLng)); | ||
| 888 | +// } | ||
| 889 | + | ||
| 890 | +// setState(() { | ||
| 891 | +// if (showloading) { | ||
| 892 | +// isloading = false; | ||
| 893 | +// } | ||
| 894 | +// }); | ||
| 895 | +// } | ||
| 896 | + | ||
| 897 | +// // void searchPoiId(String text) async { | ||
| 898 | +// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 899 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 900 | +// // Poi? poi = await AmapSearch.instance.searchPoiId( | ||
| 901 | +// // text, | ||
| 902 | +// // ); | ||
| 903 | +// // print(poi); | ||
| 904 | +// // } | ||
| 905 | + | ||
| 906 | +// // void searchAroundAddress(String text) async { | ||
| 907 | +// // await AmapLocation.instance.updatePrivacyShow(true); | ||
| 908 | +// // await AmapLocation.instance.updatePrivacyAgree(true); | ||
| 909 | +// // final poiList = await AmapSearch.instance.searchKeyword( | ||
| 910 | +// // text, | ||
| 911 | +// // city: "", | ||
| 912 | +// // ); | ||
| 913 | +// // // final poiList = await AmapSearch.instance.searchAround( | ||
| 914 | +// // // LatLng(latitude, longitude), | ||
| 915 | +// // // city: "", | ||
| 916 | +// // // radius: 100000000000000 | ||
| 917 | + | ||
| 918 | +// // // ); | ||
| 919 | + | ||
| 920 | +// // list.clear(); | ||
| 921 | +// // list.add(poiModel); | ||
| 922 | +// // for (var poi in poiList) { | ||
| 923 | +// // String? title = await poi.title; | ||
| 924 | +// // LatLng? latLng = await poi.latLng; | ||
| 925 | +// // String? cityName = await poi.cityName; | ||
| 926 | +// // String? provinceName = await poi.provinceName; | ||
| 927 | +// // String? address = await poi.address; | ||
| 928 | +// // list.add(new PoiModel( | ||
| 929 | +// // title.toString(), | ||
| 930 | +// // provinceName.toString() + cityName.toString() + address.toString(), | ||
| 931 | +// // latLng)); | ||
| 932 | +// // } | ||
| 933 | +// // setState(() { | ||
| 934 | +// // isloading = false; | ||
| 935 | +// // FocusScope.of(context).requestFocus(FocusNode()); | ||
| 936 | +// // }); | ||
| 937 | +// // } | ||
| 938 | +// } | ||
| 939 | + | ||
| 940 | +// class PoiModel { | ||
| 941 | +// LatLng? latLng; | ||
| 942 | +// String title; | ||
| 943 | +// String? address; | ||
| 944 | + | ||
| 945 | +// PoiModel(this.title, this.address, this.latLng); | ||
| 946 | +// } |
lib/pages/home/MyTestPage.dart
0 → 100644
| 1 | +// import 'package:flutter/material.dart'; | ||
| 2 | +// import 'package:speech_to_text/speech_recognition_result.dart'; | ||
| 3 | +// import 'package:speech_to_text/speech_to_text.dart' as stt; | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +// class MyTestPage extends StatefulWidget { | ||
| 10 | +// MyTestPage({Key? key}) : super(key: key); | ||
| 11 | + | ||
| 12 | +// @override | ||
| 13 | +// _MyTestPageState createState() => _MyTestPageState(); | ||
| 14 | +// } | ||
| 15 | + | ||
| 16 | +// class _MyTestPageState extends State<MyTestPage> { | ||
| 17 | +// SpeechToText _speechToText = SpeechToText(); | ||
| 18 | +// bool _speechEnabled = false; | ||
| 19 | +// String _lastWords = ''; | ||
| 20 | + | ||
| 21 | +// @override | ||
| 22 | +// void initState() { | ||
| 23 | +// super.initState(); | ||
| 24 | +// _initSpeech(); | ||
| 25 | +// } | ||
| 26 | + | ||
| 27 | +// /// This has to happen only once per app | ||
| 28 | +// void _initSpeech() async { | ||
| 29 | +// _speechEnabled = await _speechToText.initialize(); | ||
| 30 | +// setState(() {}); | ||
| 31 | +// } | ||
| 32 | + | ||
| 33 | +// /// Each time to start a speech recognition session | ||
| 34 | +// void _startListening() async { | ||
| 35 | +// await _speechToText.listen(onResult: _onSpeechResult); | ||
| 36 | +// setState(() {}); | ||
| 37 | +// } | ||
| 38 | + | ||
| 39 | +// /// Manually stop the active speech recognition session | ||
| 40 | +// /// Note that there are also timeouts that each platform enforces | ||
| 41 | +// /// and the SpeechToText plugin supports setting timeouts on the | ||
| 42 | +// /// listen method. | ||
| 43 | +// void _stopListening() async { | ||
| 44 | +// await _speechToText.stop(); | ||
| 45 | +// setState(() {}); | ||
| 46 | +// } | ||
| 47 | + | ||
| 48 | +// /// This is the callback that the SpeechToText plugin calls when | ||
| 49 | +// /// the platform returns recognized words. | ||
| 50 | +// void _onSpeechResult(SpeechRecognitionResult result) { | ||
| 51 | +// setState(() { | ||
| 52 | +// _lastWords = result.recognizedWords; | ||
| 53 | +// }); | ||
| 54 | +// } | ||
| 55 | + | ||
| 56 | +// @override | ||
| 57 | +// Widget build(BuildContext context) { | ||
| 58 | +// return Scaffold( | ||
| 59 | +// appBar: AppBar( | ||
| 60 | +// title: Text('Speech Demo'), | ||
| 61 | +// ), | ||
| 62 | +// body: Center( | ||
| 63 | +// child: Column( | ||
| 64 | +// mainAxisAlignment: MainAxisAlignment.center, | ||
| 65 | +// children: <Widget>[ | ||
| 66 | +// Container( | ||
| 67 | +// padding: EdgeInsets.all(16), | ||
| 68 | +// child: Text( | ||
| 69 | +// 'Recognized words:', | ||
| 70 | +// style: TextStyle(fontSize: 20.0), | ||
| 71 | +// ), | ||
| 72 | +// ), | ||
| 73 | +// Expanded( | ||
| 74 | +// child: Container( | ||
| 75 | +// padding: EdgeInsets.all(16), | ||
| 76 | +// child: Text( | ||
| 77 | +// // If listening is active show the recognized words | ||
| 78 | +// _speechToText.isListening | ||
| 79 | +// ? '$_lastWords' | ||
| 80 | +// // If listening isn't active but could be tell the user | ||
| 81 | +// // how to start it, otherwise indicate that speech | ||
| 82 | +// // recognition is not yet ready or not supported on | ||
| 83 | +// // the target device | ||
| 84 | +// : _speechEnabled | ||
| 85 | +// ? 'Tap the microphone to start listening...' | ||
| 86 | +// : 'Speech not available', | ||
| 87 | +// ), | ||
| 88 | +// ), | ||
| 89 | +// ), | ||
| 90 | +// ], | ||
| 91 | +// ), | ||
| 92 | +// ), | ||
| 93 | +// floatingActionButton: FloatingActionButton( | ||
| 94 | +// onPressed: | ||
| 95 | +// // If not yet listening for speech start, otherwise stop | ||
| 96 | +// _speechToText.isNotListening ? _startListening : _stopListening, | ||
| 97 | +// tooltip: 'Listen', | ||
| 98 | +// child: Icon(_speechToText.isNotListening ? Icons.mic_off : Icons.mic), | ||
| 99 | +// ), | ||
| 100 | +// ); | ||
| 101 | +// } | ||
| 102 | +// } |
lib/pages/home/ProviderDemoApp.dart
0 → 100644
| 1 | +// import 'dart:async'; | ||
| 2 | + | ||
| 3 | +// import 'package:flutter/material.dart'; | ||
| 4 | +// import 'package:one_key/pages/home/RecognitionResultsWidget.dart'; | ||
| 5 | +// import 'package:provider/provider.dart'; | ||
| 6 | +// import 'package:speech_to_text/speech_to_text.dart'; | ||
| 7 | +// import 'package:speech_to_text/speech_to_text_provider.dart'; | ||
| 8 | + | ||
| 9 | +// class ProviderDemoApp extends StatefulWidget { | ||
| 10 | +// const ProviderDemoApp({super.key}); | ||
| 11 | + | ||
| 12 | +// @override | ||
| 13 | +// State<ProviderDemoApp> createState() => _ProviderDemoAppState(); | ||
| 14 | +// } | ||
| 15 | + | ||
| 16 | +// class _ProviderDemoAppState extends State<ProviderDemoApp> { | ||
| 17 | +// final SpeechToText speech = SpeechToText(); | ||
| 18 | +// late SpeechToTextProvider speechProvider; | ||
| 19 | + | ||
| 20 | +// @override | ||
| 21 | +// void initState() { | ||
| 22 | +// super.initState(); | ||
| 23 | +// speechProvider = SpeechToTextProvider(speech); | ||
| 24 | +// initSpeechState(); | ||
| 25 | +// } | ||
| 26 | + | ||
| 27 | +// Future<void> initSpeechState() async { | ||
| 28 | +// bool ggggg = await speechProvider.initialize(); | ||
| 29 | +// print(ggggg); | ||
| 30 | +// } | ||
| 31 | + | ||
| 32 | +// @override | ||
| 33 | +// Widget build(BuildContext context) { | ||
| 34 | +// return ChangeNotifierProvider<SpeechToTextProvider>.value( | ||
| 35 | +// value: speechProvider, | ||
| 36 | +// child: MaterialApp( | ||
| 37 | +// home: Scaffold( | ||
| 38 | +// appBar: AppBar( | ||
| 39 | +// title: const Text('标题'), | ||
| 40 | +// ), | ||
| 41 | +// body: const SpeechProviderExampleWidget(), | ||
| 42 | +// ), | ||
| 43 | +// ), | ||
| 44 | +// ); | ||
| 45 | +// } | ||
| 46 | +// } | ||
| 47 | + | ||
| 48 | +// class SpeechProviderExampleWidget extends StatefulWidget { | ||
| 49 | +// const SpeechProviderExampleWidget({super.key}); | ||
| 50 | + | ||
| 51 | +// @override | ||
| 52 | +// SpeechProviderExampleWidgetState createState() => | ||
| 53 | +// SpeechProviderExampleWidgetState(); | ||
| 54 | +// } | ||
| 55 | + | ||
| 56 | +// class SpeechProviderExampleWidgetState | ||
| 57 | +// extends State<SpeechProviderExampleWidget> { | ||
| 58 | +// String _currentLocaleId = ''; | ||
| 59 | + | ||
| 60 | +// void _setCurrentLocale(SpeechToTextProvider speechProvider) { | ||
| 61 | +// if (speechProvider.isAvailable && _currentLocaleId.isEmpty) { | ||
| 62 | +// _currentLocaleId = speechProvider.systemLocale?.localeId ?? ''; | ||
| 63 | +// } | ||
| 64 | +// } | ||
| 65 | + | ||
| 66 | +// @override | ||
| 67 | +// Widget build(BuildContext context) { | ||
| 68 | +// var speechProvider = Provider.of<SpeechToTextProvider>(context); | ||
| 69 | +// if (speechProvider.isNotAvailable) { | ||
| 70 | +// return const Center( | ||
| 71 | +// child: Text( | ||
| 72 | +// 'Speech recognition not available, no permission or not available on the device.'), | ||
| 73 | +// ); | ||
| 74 | +// } | ||
| 75 | +// _setCurrentLocale(speechProvider); | ||
| 76 | +// return Column(children: [ | ||
| 77 | +// const Center( | ||
| 78 | +// child: Text( | ||
| 79 | +// 'Speech recognition available', | ||
| 80 | +// style: TextStyle(fontSize: 22.0), | ||
| 81 | +// ), | ||
| 82 | +// ), | ||
| 83 | +// Column( | ||
| 84 | +// children: <Widget>[ | ||
| 85 | +// Row( | ||
| 86 | +// mainAxisAlignment: MainAxisAlignment.spaceAround, | ||
| 87 | +// children: <Widget>[ | ||
| 88 | +// TextButton( | ||
| 89 | +// onPressed: | ||
| 90 | +// !speechProvider.isAvailable || speechProvider.isListening | ||
| 91 | +// ? null | ||
| 92 | +// : () => speechProvider.listen( | ||
| 93 | +// partialResults: true, localeId: _currentLocaleId), | ||
| 94 | +// child: const Text('Start'), | ||
| 95 | +// ), | ||
| 96 | +// TextButton( | ||
| 97 | +// onPressed: speechProvider.isListening | ||
| 98 | +// ? () => speechProvider.stop() | ||
| 99 | +// : null, | ||
| 100 | +// child: const Text('Stop'), | ||
| 101 | +// ), | ||
| 102 | +// TextButton( | ||
| 103 | +// onPressed: speechProvider.isListening | ||
| 104 | +// ? () => speechProvider.cancel() | ||
| 105 | +// : null, | ||
| 106 | +// child: const Text('Cancel'), | ||
| 107 | +// ), | ||
| 108 | +// ], | ||
| 109 | +// ), | ||
| 110 | +// Row( | ||
| 111 | +// mainAxisAlignment: MainAxisAlignment.spaceAround, | ||
| 112 | +// children: <Widget>[ | ||
| 113 | +// DropdownButton( | ||
| 114 | +// onChanged: (selectedVal) => _switchLang(selectedVal), | ||
| 115 | +// value: _currentLocaleId, | ||
| 116 | +// items: speechProvider.locales | ||
| 117 | +// .map( | ||
| 118 | +// (localeName) => DropdownMenuItem( | ||
| 119 | +// value: localeName.localeId, | ||
| 120 | +// child: Text(localeName.name), | ||
| 121 | +// ), | ||
| 122 | +// ) | ||
| 123 | +// .toList(), | ||
| 124 | +// ), | ||
| 125 | +// ], | ||
| 126 | +// ) | ||
| 127 | +// ], | ||
| 128 | +// ), | ||
| 129 | +// const Expanded( | ||
| 130 | +// flex: 4, | ||
| 131 | +// child: RecognitionResultsWidget(), | ||
| 132 | +// ), | ||
| 133 | +// Expanded( | ||
| 134 | +// flex: 1, | ||
| 135 | +// child: Column( | ||
| 136 | +// children: <Widget>[ | ||
| 137 | +// const Center( | ||
| 138 | +// child: Text( | ||
| 139 | +// 'Error Status', | ||
| 140 | +// style: TextStyle(fontSize: 22.0), | ||
| 141 | +// ), | ||
| 142 | +// ), | ||
| 143 | +// Center( | ||
| 144 | +// child: speechProvider.hasError | ||
| 145 | +// ? Text(speechProvider.lastError!.errorMsg) | ||
| 146 | +// : Container(), | ||
| 147 | +// ), | ||
| 148 | +// ], | ||
| 149 | +// ), | ||
| 150 | +// ), | ||
| 151 | +// Container( | ||
| 152 | +// padding: const EdgeInsets.symmetric(vertical: 20), | ||
| 153 | +// color: Theme.of(context).colorScheme.surface, | ||
| 154 | +// child: Center( | ||
| 155 | +// child: speechProvider.isListening | ||
| 156 | +// ? const Text( | ||
| 157 | +// "I'm listening...", | ||
| 158 | +// style: TextStyle(fontWeight: FontWeight.bold), | ||
| 159 | +// ) | ||
| 160 | +// : const Text( | ||
| 161 | +// 'Not listening', | ||
| 162 | +// style: TextStyle(fontWeight: FontWeight.bold), | ||
| 163 | +// ), | ||
| 164 | +// ), | ||
| 165 | +// ), | ||
| 166 | +// ]); | ||
| 167 | +// } | ||
| 168 | + | ||
| 169 | +// void _switchLang(selectedVal) { | ||
| 170 | +// setState(() { | ||
| 171 | +// _currentLocaleId = selectedVal; | ||
| 172 | +// }); | ||
| 173 | +// debugPrint(selectedVal); | ||
| 174 | +// } | ||
| 175 | +// } |
lib/pages/home/RecognitionResultsWidget.dart
0 → 100644
| 1 | +// import 'package:flutter/material.dart'; | ||
| 2 | +// import 'package:provider/provider.dart'; | ||
| 3 | +// import 'package:speech_to_text/speech_to_text_provider.dart'; | ||
| 4 | + | ||
| 5 | +// /// Show the most recently recognized speech results and use the level | ||
| 6 | +// /// information to animate the microphone. | ||
| 7 | +// /// | ||
| 8 | +// /// Note that the provider is initialized elsewhere and just accessed | ||
| 9 | +// /// here. | ||
| 10 | +// class RecognitionResultsWidget extends StatelessWidget { | ||
| 11 | +// const RecognitionResultsWidget({super.key}); | ||
| 12 | + | ||
| 13 | +// @override | ||
| 14 | +// Widget build(BuildContext context) { | ||
| 15 | +// var speechProvider = Provider.of<SpeechToTextProvider>(context); | ||
| 16 | +// return Column( | ||
| 17 | +// children: <Widget>[ | ||
| 18 | +// const Center( | ||
| 19 | +// child: Text( | ||
| 20 | +// 'Recognized Words', | ||
| 21 | +// style: TextStyle(fontSize: 22.0), | ||
| 22 | +// ), | ||
| 23 | +// ), | ||
| 24 | +// Expanded( | ||
| 25 | +// child: Stack( | ||
| 26 | +// children: <Widget>[ | ||
| 27 | +// Container( | ||
| 28 | +// color: Theme.of(context).secondaryHeaderColor, | ||
| 29 | +// child: Center( | ||
| 30 | +// child: Text( | ||
| 31 | +// speechProvider.lastResult?.recognizedWords ?? '', | ||
| 32 | +// textAlign: TextAlign.center, | ||
| 33 | +// ), | ||
| 34 | +// ), | ||
| 35 | +// ), | ||
| 36 | +// Positioned.fill( | ||
| 37 | +// bottom: 10, | ||
| 38 | +// child: Align( | ||
| 39 | +// alignment: Alignment.bottomCenter, | ||
| 40 | +// child: Container( | ||
| 41 | +// width: 40, | ||
| 42 | +// height: 40, | ||
| 43 | +// alignment: Alignment.center, | ||
| 44 | +// decoration: BoxDecoration( | ||
| 45 | +// boxShadow: [ | ||
| 46 | +// BoxShadow( | ||
| 47 | +// blurRadius: .26, | ||
| 48 | +// spreadRadius: speechProvider.lastLevel * 1.5, | ||
| 49 | +// color: Colors.black.withOpacity(.05)) | ||
| 50 | +// ], | ||
| 51 | +// color: Colors.white, | ||
| 52 | +// borderRadius: const BorderRadius.all(Radius.circular(50)), | ||
| 53 | +// ), | ||
| 54 | +// child: IconButton( | ||
| 55 | +// icon: const Icon(Icons.mic), | ||
| 56 | +// onPressed: () {}, | ||
| 57 | +// ), | ||
| 58 | +// ), | ||
| 59 | +// ), | ||
| 60 | +// ), | ||
| 61 | +// ], | ||
| 62 | +// ), | ||
| 63 | +// ), | ||
| 64 | +// ], | ||
| 65 | +// ); | ||
| 66 | +// } | ||
| 67 | +// } |
lib/pages/home/demo.dart
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright 2018, 2019, 2020, 2021 Dooboolab. | ||
| 3 | + * | ||
| 4 | + * This file is part of Flutter-Sound. | ||
| 5 | + * | ||
| 6 | + * Flutter-Sound is free software: you can redistribute it and/or modify | ||
| 7 | + * it under the terms of the Mozilla Public License version 2 (MPL2.0), | ||
| 8 | + * as published by the Mozilla organization. | ||
| 9 | + * | ||
| 10 | + * Flutter-Sound is distributed in the hope that it will be useful, | ||
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | + * MPL General Public License for more details. | ||
| 14 | + * | ||
| 15 | + * This Source Code Form is subject to the terms of the Mozilla Public | ||
| 16 | + * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| 17 | + * file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| 18 | + */ | ||
| 19 | + | ||
| 20 | +import 'dart:async'; | ||
| 21 | +import 'dart:io'; | ||
| 22 | +import 'dart:math'; | ||
| 23 | +import 'dart:typed_data' show Uint8List; | ||
| 24 | + | ||
| 25 | +import 'package:audio_session/audio_session.dart'; | ||
| 26 | +import 'package:flutter/material.dart'; | ||
| 27 | +import 'package:path_provider/path_provider.dart'; | ||
| 28 | +import 'package:flutter/services.dart' show rootBundle; | ||
| 29 | +import 'package:intl/date_symbol_data_local.dart'; | ||
| 30 | +import 'package:intl/intl.dart' show DateFormat; | ||
| 31 | +import 'package:flutter_sound/flutter_sound.dart'; | ||
| 32 | +import 'package:permission_handler/permission_handler.dart'; | ||
| 33 | +import 'package:flutter/foundation.dart' show kIsWeb; | ||
| 34 | +import 'dart:typed_data'; | ||
| 35 | + | ||
| 36 | +/* | ||
| 37 | + | ||
| 38 | +This is a demo of what it is possible to do with Flutter Sound. The code of this demo app is not so simple. | ||
| 39 | + | ||
| 40 | +Flutter Sound beginners : you probably should look to [SimplePlayback](fs-ex_simple_playback.html) | ||
| 41 | +and [SimpleRecorder](fs-ex_simple_recorder.html) | ||
| 42 | + | ||
| 43 | +The biggest interest of this Demo is that it shows most of the features of Flutter Sound : | ||
| 44 | + | ||
| 45 | +* Plays from various media with various codecs | ||
| 46 | +* Records to various media with various codecs | ||
| 47 | +* Pause and Resume control from recording or playback | ||
| 48 | +* Shows how to use a stream for getting the playback \(or recoding\) events | ||
| 49 | +* Shows how to specify a callback function when a playback is terminated, | ||
| 50 | +* Shows how to record to a Stream or playback from a stream | ||
| 51 | +* ... | ||
| 52 | + | ||
| 53 | + */ | ||
| 54 | +/// | ||
| 55 | +const int cstSAMPLERATE = 8000; | ||
| 56 | +const int cstCHANNELNB = 2; | ||
| 57 | +const int cstBITRATE = 16000; | ||
| 58 | + | ||
| 59 | +/// | ||
| 60 | +const int cstBLOCKSIZE = 4096; | ||
| 61 | + | ||
| 62 | +/// | ||
| 63 | +enum Media { | ||
| 64 | + /// | ||
| 65 | + file, | ||
| 66 | + | ||
| 67 | + /// | ||
| 68 | + buffer, | ||
| 69 | + | ||
| 70 | + /// | ||
| 71 | + asset, | ||
| 72 | + | ||
| 73 | + /// | ||
| 74 | + stream, | ||
| 75 | + | ||
| 76 | + /// | ||
| 77 | + remoteExampleFile, | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | +/// | ||
| 81 | +enum AudioState { | ||
| 82 | + /// | ||
| 83 | + isPlaying, | ||
| 84 | + | ||
| 85 | + /// | ||
| 86 | + isPaused, | ||
| 87 | + | ||
| 88 | + /// | ||
| 89 | + isStopped, | ||
| 90 | + | ||
| 91 | + /// | ||
| 92 | + isRecording, | ||
| 93 | + | ||
| 94 | + /// | ||
| 95 | + isRecordingPaused, | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +/* | ||
| 99 | +/// | ||
| 100 | +final exampleAudioFilePathAACAdts = | ||
| 101 | + //'https://filesamples.com/samples/audio/aac/sample1.aac'; | ||
| 102 | + 'https://www.canardoux.xyz/tau_sound/web_example/sample.aac'; | ||
| 103 | + | ||
| 104 | +/// | ||
| 105 | +final exampleAudioFilePathWave = | ||
| 106 | + 'http://5.189.150.137:5000/download_audio/CantinaBand3.wav'; | ||
| 107 | + | ||
| 108 | +/// | ||
| 109 | +final exampleAudioFilePathMP3 = | ||
| 110 | + 'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3'; | ||
| 111 | + | ||
| 112 | +/// | ||
| 113 | +final exampleAudioFilePathOPUS = | ||
| 114 | + 'https://whatsapp-inbox-server.clare.ai/api/file/showFile?fileName=data/audios/e3f16eb2-10c3-45c9-b0fa-900c94cbe805.opus&token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxMWI5YjQ3Zi1jMzBjLTRlZDMtYTFhNy1iNmYxNzRkMWQ1NTYiLCJ1bmlxdWVfbmFtZSI6InZlcm5hbEBjbGFyZS5haSIsIm5hbWVpZCI6InZlcm5hbEBjbGFyZS5haSIsImVtYWlsIjoidmVybmFsQGNsYXJlLmFpIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiRVhURVJOQUxfQURNSU5JU1RSQVRPUiIsImV4cCI6MjUzNDAyMzAwODAwLCJpc3MiOiJDbGFyZV9BSSIsImF1ZCI6IkNsYXJlX0FJIn0.yXVZ3n_lYYvJ1rGyF2mVh-80HuS0EEp7sQepxn9rGcY'; | ||
| 115 | +/// | ||
| 116 | +final albumArtPath = | ||
| 117 | + 'https://file-examples-com.github.io/uploads/2017/10/file_example_PNG_500kB.png'; | ||
| 118 | +*/ | ||
| 119 | +const albumArtPathRemote = | ||
| 120 | + 'https://flutter-sound.canardoux.xyz/web_example/assets/extract/3iob.png'; | ||
| 121 | +const albumArtPath = | ||
| 122 | + 'https://file-examples-com.github.io/uploads/2017/10/file_example_PNG_500kB.png'; | ||
| 123 | + | ||
| 124 | +/// | ||
| 125 | +class Demo extends StatefulWidget { | ||
| 126 | + const Demo({super.key}); | ||
| 127 | + @override | ||
| 128 | + State<Demo> createState() => _MyAppState(); | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +class _MyAppState extends State<Demo> { | ||
| 132 | + bool _isRecording = false; | ||
| 133 | + final List<String?> _path = [ | ||
| 134 | + null, | ||
| 135 | + null, | ||
| 136 | + null, | ||
| 137 | + null, | ||
| 138 | + null, | ||
| 139 | + null, | ||
| 140 | + null, | ||
| 141 | + null, | ||
| 142 | + null, | ||
| 143 | + null, | ||
| 144 | + null, | ||
| 145 | + null, | ||
| 146 | + null, | ||
| 147 | + null, | ||
| 148 | + null, | ||
| 149 | + null, | ||
| 150 | + null, | ||
| 151 | + null, | ||
| 152 | + null, | ||
| 153 | + null, | ||
| 154 | + ]; | ||
| 155 | + | ||
| 156 | + List<String> assetSample = [ | ||
| 157 | + 'assets/samples/sample.aac', | ||
| 158 | + 'assets/samples/sample.aac', | ||
| 159 | + 'assets/samples/sample.opus', | ||
| 160 | + 'assets/samples/sample_opus.caf', | ||
| 161 | + 'assets/samples/sample.mp3', | ||
| 162 | + 'assets/samples/sample.ogg', | ||
| 163 | + 'assets/samples/sample_s16_2ch.raw', // Raw PCM int16 | ||
| 164 | + 'assets/samples/sample_2ch.wav', // int16 wav stereo | ||
| 165 | + 'assets/samples/sample.aiff', | ||
| 166 | + 'assets/samples/sample_pcm.caf', | ||
| 167 | + 'assets/samples/sample.flac', | ||
| 168 | + 'assets/samples/sample.mp4', | ||
| 169 | + 'assets/samples/sample.amr', // amrNB | ||
| 170 | + 'assets/samples/sample_xxx.amr', // amrWB | ||
| 171 | + 'assets/samples/sample_xxx.pcm', // pcm8 | ||
| 172 | + 'assets/samples/sample_f32_2ch.raw', // Raw pcmFloat32 | ||
| 173 | + '', // 'assets/samples/sample_xxx.pcm', // pcmWebM | ||
| 174 | + 'assets/samples/sample_opus.webm', // opusWebM | ||
| 175 | + 'assets/samples/sample_vorbis.webm', // vorbisWebM | ||
| 176 | + 'assets/samples/sample_f32_2ch.wav', // wav Float32 stereo | ||
| 177 | + ]; | ||
| 178 | + | ||
| 179 | + List<String> remoteSample = [ | ||
| 180 | + 'https://fs-doc.vercel.app/extract/01.aac', // 'assets/samples/sample.aac', | ||
| 181 | + 'https://fs-doc.vercel.app/extract/01.aac', // 'assets/samples/sample.aac', | ||
| 182 | + 'https://fs-doc.vercel.app/extract/08.opus', // 'assets/samples/sample.opus', | ||
| 183 | + 'https://fs-doc.vercel.app/extract/04-opus.caf', // 'assets/samples/sample_opus.caf', | ||
| 184 | + 'https://fs-doc.vercel.app/extract/05.mp3', // 'assets/samples/sample.mp3', | ||
| 185 | + 'https://fs-doc.vercel.app/extract/07.ogg', // 'assets/samples/sample.ogg', | ||
| 186 | + 'https://fs-doc.vercel.app/extract/sample_s16_2ch.pcm', // Raw PCM int16 | ||
| 187 | + 'https://fs-doc.vercel.app/extract/sample_2ch.wav', // int16 wav stereo | ||
| 188 | + 'https://fs-doc.vercel.app/extract/02.aiff', // 'assets/samples/sample.aiff', | ||
| 189 | + 'https://fs-doc.vercel.app/extract/01-pcm.caf', // 'assets/samples/sample_pcm.caf', | ||
| 190 | + 'https://fs-doc.vercel.app/extract/04.flac', // 'assets/samples/sample.flac', | ||
| 191 | + 'https://fs-doc.vercel.app/extract/06.mp4', // 'assets/samples/sample.mp4', | ||
| 192 | + 'https://fs-doc.vercel.app/extract/03.amr', // 'assets/samples/sample.amr', // amrNB | ||
| 193 | + 'https://fs-doc.vercel.app/extract/03.amr', // 'assets/samples/sample_xxx.amr', // amrWB | ||
| 194 | + 'https://fs-doc.vercel.app/extract/09-pcm8.raw', // 'assets/samples/sample_xxx.pcm', // pcm8 | ||
| 195 | + 'https://fs-doc.vercel.app/extract/sample_f32_2ch.raw', // Raw pcmFloat32 | ||
| 196 | + '', // pcmWebM | ||
| 197 | + 'https://fs-doc.vercel.app/extract/02-opus.webm', // 'assets/samples/sample_opus.webm', // opusWebM | ||
| 198 | + 'https://fs-doc.vercel.app/extract/03-vorbis.webm', // 'assets/samples/sample_vorbis.webm', // vorbisWebM | ||
| 199 | + 'https://fs-doc.vercel.app/extract/sample_f32_2ch.wav', // wav Float32 stereo | ||
| 200 | + ]; | ||
| 201 | + | ||
| 202 | + StreamSubscription? _recorderSubscription; | ||
| 203 | + StreamSubscription? _playerSubscription; | ||
| 204 | + StreamSubscription? _recordingDataSubscription; | ||
| 205 | + | ||
| 206 | + FlutterSoundPlayer playerModule = FlutterSoundPlayer(); | ||
| 207 | + FlutterSoundRecorder recorderModule = FlutterSoundRecorder(); | ||
| 208 | + | ||
| 209 | + String _recorderTxt = '00:00:00'; | ||
| 210 | + String _playerTxt = '00:00:00'; | ||
| 211 | + double? _dbLevel; | ||
| 212 | + | ||
| 213 | + double sliderCurrentPosition = 0.0; | ||
| 214 | + double maxDuration = 1.0; | ||
| 215 | + Media? _media = Media.remoteExampleFile; | ||
| 216 | + Codec _codec = Codec.aacMP4; | ||
| 217 | + | ||
| 218 | + bool? _encoderSupported = true; // Optimist | ||
| 219 | + bool _decoderSupported = true; // Optimist | ||
| 220 | + | ||
| 221 | + StreamController<Uint8List>? recordingDataController; | ||
| 222 | + IOSink? sink; | ||
| 223 | + | ||
| 224 | + Future<void> _initializeExample() async { | ||
| 225 | + await playerModule.closePlayer(); | ||
| 226 | + await playerModule.openPlayer(); | ||
| 227 | + await playerModule | ||
| 228 | + .setSubscriptionDuration(const Duration(milliseconds: 10)); | ||
| 229 | + await recorderModule | ||
| 230 | + .setSubscriptionDuration(const Duration(milliseconds: 100)); | ||
| 231 | + await initializeDateFormatting(); | ||
| 232 | + await setCodec(_codec); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + Future<void> openTheRecorder() async { | ||
| 236 | + if (!kIsWeb) { | ||
| 237 | + var status = await Permission.microphone.request(); | ||
| 238 | + if (status != PermissionStatus.granted) { | ||
| 239 | + throw RecordingPermissionException('Microphone permission not granted'); | ||
| 240 | + } | ||
| 241 | + } | ||
| 242 | + await recorderModule.openRecorder(); | ||
| 243 | + | ||
| 244 | + if (!await recorderModule.isEncoderSupported(_codec) && kIsWeb) { | ||
| 245 | + _codec = Codec.opusWebM; | ||
| 246 | + } | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + Future<void> init() async { | ||
| 250 | + await openTheRecorder(); | ||
| 251 | + await _initializeExample(); | ||
| 252 | + | ||
| 253 | + if ((!kIsWeb) && Platform.isAndroid) { | ||
| 254 | + await copyAssets(); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + final session = await AudioSession.instance; | ||
| 258 | + await session.configure(AudioSessionConfiguration( | ||
| 259 | + avAudioSessionCategory: AVAudioSessionCategory.playAndRecord, | ||
| 260 | + avAudioSessionCategoryOptions: | ||
| 261 | + AVAudioSessionCategoryOptions.allowBluetooth | | ||
| 262 | + AVAudioSessionCategoryOptions.defaultToSpeaker, | ||
| 263 | + avAudioSessionMode: AVAudioSessionMode.spokenAudio, | ||
| 264 | + avAudioSessionRouteSharingPolicy: | ||
| 265 | + AVAudioSessionRouteSharingPolicy.defaultPolicy, | ||
| 266 | + avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none, | ||
| 267 | + androidAudioAttributes: const AndroidAudioAttributes( | ||
| 268 | + contentType: AndroidAudioContentType.speech, | ||
| 269 | + flags: AndroidAudioFlags.none, | ||
| 270 | + usage: AndroidAudioUsage.voiceCommunication, | ||
| 271 | + ), | ||
| 272 | + androidAudioFocusGainType: AndroidAudioFocusGainType.gain, | ||
| 273 | + androidWillPauseWhenDucked: true, | ||
| 274 | + )); | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + Future<void> copyAssets() async { | ||
| 278 | + var dataBuffer = | ||
| 279 | + (await rootBundle.load('assets/canardo.png')).buffer.asUint8List(); | ||
| 280 | + var path = '${await playerModule.getResourcePath()}/assets'; | ||
| 281 | + if (!await Directory(path).exists()) { | ||
| 282 | + await Directory(path).create(recursive: true); | ||
| 283 | + } | ||
| 284 | + await File('$path/canardo.png').writeAsBytes(dataBuffer); | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + @override | ||
| 288 | + void initState() { | ||
| 289 | + super.initState(); | ||
| 290 | + init(); | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + void cancelRecorderSubscriptions() { | ||
| 294 | + if (_recorderSubscription != null) { | ||
| 295 | + _recorderSubscription!.cancel(); | ||
| 296 | + _recorderSubscription = null; | ||
| 297 | + } | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + void cancelPlayerSubscriptions() { | ||
| 301 | + if (_playerSubscription != null) { | ||
| 302 | + _playerSubscription!.cancel(); | ||
| 303 | + _playerSubscription = null; | ||
| 304 | + } | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + void cancelRecordingDataSubscription() { | ||
| 308 | + if (_recordingDataSubscription != null) { | ||
| 309 | + _recordingDataSubscription!.cancel(); | ||
| 310 | + _recordingDataSubscription = null; | ||
| 311 | + } | ||
| 312 | + recordingDataController = null; | ||
| 313 | + if (sink != null) { | ||
| 314 | + sink!.close(); | ||
| 315 | + sink = null; | ||
| 316 | + } | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + @override | ||
| 320 | + void dispose() { | ||
| 321 | + super.dispose(); | ||
| 322 | + cancelPlayerSubscriptions(); | ||
| 323 | + cancelRecorderSubscriptions(); | ||
| 324 | + cancelRecordingDataSubscription(); | ||
| 325 | + releaseFlauto(); | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + Future<void> releaseFlauto() async { | ||
| 329 | + try { | ||
| 330 | + await playerModule.closePlayer(); | ||
| 331 | + await recorderModule.closeRecorder(); | ||
| 332 | + } on Exception { | ||
| 333 | + playerModule.logger.e('Released unsuccessful'); | ||
| 334 | + } | ||
| 335 | + } | ||
| 336 | + | ||
| 337 | + void startRecorder() async { | ||
| 338 | + try { | ||
| 339 | + // Request Microphone permission if needed | ||
| 340 | + if (!kIsWeb) { | ||
| 341 | + var status = await Permission.microphone.request(); | ||
| 342 | + if (status != PermissionStatus.granted) { | ||
| 343 | + throw RecordingPermissionException( | ||
| 344 | + 'Microphone permission not granted'); | ||
| 345 | + } | ||
| 346 | + } | ||
| 347 | + var path = ''; | ||
| 348 | + if (!kIsWeb) { | ||
| 349 | + var tempDir = await getTemporaryDirectory(); | ||
| 350 | + path = '${tempDir.path}/flutter_sound${ext[_codec.index]}'; | ||
| 351 | + } else { | ||
| 352 | + path = '_flutter_sound${ext[_codec.index]}'; | ||
| 353 | + } | ||
| 354 | + | ||
| 355 | + if (_media == Media.stream) { | ||
| 356 | + assert(_codec == Codec.pcm16); | ||
| 357 | + if (!kIsWeb) { | ||
| 358 | + var outputFile = File(path); | ||
| 359 | + if (outputFile.existsSync()) { | ||
| 360 | + await outputFile.delete(); | ||
| 361 | + } | ||
| 362 | + sink = outputFile.openWrite(); | ||
| 363 | + } else { | ||
| 364 | + sink = null; // TODO | ||
| 365 | + } | ||
| 366 | + recordingDataController = StreamController<Uint8List>(); | ||
| 367 | + _recordingDataSubscription = | ||
| 368 | + recordingDataController!.stream.listen((buffer) { | ||
| 369 | + sink!.add(buffer); | ||
| 370 | + }); | ||
| 371 | + await recorderModule.startRecorder( | ||
| 372 | + toStream: recordingDataController!.sink, | ||
| 373 | + bufferSize: 128, | ||
| 374 | + codec: _codec, | ||
| 375 | + numChannels: cstCHANNELNB, | ||
| 376 | + sampleRate: cstSAMPLERATE, // tSTREAMSAMPLERATE, //tSAMPLERATE, | ||
| 377 | + ); | ||
| 378 | + } else { | ||
| 379 | + await recorderModule.startRecorder( | ||
| 380 | + toFile: path, | ||
| 381 | + codec: _codec, | ||
| 382 | + bitRate: cstBITRATE, | ||
| 383 | + numChannels: cstCHANNELNB, | ||
| 384 | + sampleRate: | ||
| 385 | + cstSAMPLERATE, // (_codec == Codec.pcm16) ? tSTREAMSAMPLERATE : tSAMPLERATE, | ||
| 386 | + ); | ||
| 387 | + } | ||
| 388 | + recorderModule.logger.d('startRecorder'); | ||
| 389 | + | ||
| 390 | + _recorderSubscription = recorderModule.onProgress!.listen((e) { | ||
| 391 | + var date = DateTime.fromMillisecondsSinceEpoch( | ||
| 392 | + e.duration.inMilliseconds, | ||
| 393 | + isUtc: true); | ||
| 394 | + var txt = DateFormat('mm:ss:SS', 'en_GB').format(date); | ||
| 395 | + | ||
| 396 | + setState(() { | ||
| 397 | + _recorderTxt = txt.substring(0, 8); | ||
| 398 | + _dbLevel = e.decibels; | ||
| 399 | + }); | ||
| 400 | + }); | ||
| 401 | + | ||
| 402 | + setState(() { | ||
| 403 | + _isRecording = true; | ||
| 404 | + _path[_codec.index] = path; | ||
| 405 | + }); | ||
| 406 | + } on Exception catch (err) { | ||
| 407 | + recorderModule.logger.e('startRecorder error: $err'); | ||
| 408 | + setState(() { | ||
| 409 | + stopRecorder(); | ||
| 410 | + _isRecording = false; | ||
| 411 | + cancelRecordingDataSubscription(); | ||
| 412 | + cancelRecorderSubscriptions(); | ||
| 413 | + }); | ||
| 414 | + } | ||
| 415 | + } | ||
| 416 | + | ||
| 417 | + void stopRecorder() async { | ||
| 418 | + try { | ||
| 419 | + await recorderModule.stopRecorder(); | ||
| 420 | + recorderModule.logger.d('stopRecorder'); | ||
| 421 | + cancelRecorderSubscriptions(); | ||
| 422 | + cancelRecordingDataSubscription(); | ||
| 423 | + } on Exception catch (err) { | ||
| 424 | + recorderModule.logger.d('stopRecorder error: $err'); | ||
| 425 | + } | ||
| 426 | + setState(() { | ||
| 427 | + _isRecording = false; | ||
| 428 | + }); | ||
| 429 | + } | ||
| 430 | + | ||
| 431 | + Future<bool> fileExists(String path) async { | ||
| 432 | + return await File(path).exists(); | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + // In this simple example, we just load a file in memory.This is stupid but just for demonstration of startPlayerFromBuffer() | ||
| 436 | + Future<Uint8List?> makeBuffer(String path) async { | ||
| 437 | + try { | ||
| 438 | + if (!await fileExists(path)) return null; | ||
| 439 | + var file = File(path); | ||
| 440 | + file.openRead(); | ||
| 441 | + var contents = await file.readAsBytes(); | ||
| 442 | + playerModule.logger.i('The file is ${contents.length} bytes long.'); | ||
| 443 | + return contents; | ||
| 444 | + } on Exception catch (e) { | ||
| 445 | + playerModule.logger.e(e); | ||
| 446 | + return null; | ||
| 447 | + } | ||
| 448 | + } | ||
| 449 | + | ||
| 450 | + void _addListeners() { | ||
| 451 | + cancelPlayerSubscriptions(); | ||
| 452 | + _playerSubscription = playerModule.onProgress!.listen((e) { | ||
| 453 | + maxDuration = e.duration.inMilliseconds.toDouble(); | ||
| 454 | + if (maxDuration <= 0) maxDuration = 0.0; | ||
| 455 | + | ||
| 456 | + sliderCurrentPosition = | ||
| 457 | + min(e.position.inMilliseconds.toDouble(), maxDuration); | ||
| 458 | + if (sliderCurrentPosition < 0.0) { | ||
| 459 | + sliderCurrentPosition = 0.0; | ||
| 460 | + } | ||
| 461 | + | ||
| 462 | + var date = DateTime.fromMillisecondsSinceEpoch(e.position.inMilliseconds, | ||
| 463 | + isUtc: true); | ||
| 464 | + var txt = DateFormat('mm:ss:SS', 'en_GB').format(date); | ||
| 465 | + setState(() { | ||
| 466 | + _playerTxt = txt.substring(0, 8); | ||
| 467 | + }); | ||
| 468 | + }); | ||
| 469 | + } | ||
| 470 | + | ||
| 471 | + Future<Uint8List> _readFileByte(String filePath) async { | ||
| 472 | + var myUri = Uri.parse(filePath); | ||
| 473 | + var audioFile = File.fromUri(myUri); | ||
| 474 | + Uint8List bytes; | ||
| 475 | + var b = await audioFile.readAsBytes(); | ||
| 476 | + bytes = Uint8List.fromList(b); | ||
| 477 | + playerModule.logger.d('reading of bytes is completed'); | ||
| 478 | + return bytes; | ||
| 479 | + } | ||
| 480 | + | ||
| 481 | + Future<Uint8List> getAssetData(String path) async { | ||
| 482 | + var asset = await rootBundle.load(path); | ||
| 483 | + return asset.buffer.asUint8List(); | ||
| 484 | + } | ||
| 485 | + | ||
| 486 | + /* | ||
| 487 | + Future<void> feedHim(String path) async { | ||
| 488 | + var data = await _readFileByte(path); | ||
| 489 | + return await playerModule.feedFromStream(data); | ||
| 490 | + } | ||
| 491 | +*/ | ||
| 492 | + | ||
| 493 | + final int blockSize = 4096; | ||
| 494 | + Future<void> feedHim(String path) async { | ||
| 495 | + var buffer = await _readFileByte(path); | ||
| 496 | + //var buffer = await getAssetData('assets/samples/sample.pcm'); | ||
| 497 | + | ||
| 498 | + var lnData = 0; | ||
| 499 | + var totalLength = buffer.length; | ||
| 500 | + while (totalLength > 0 && !playerModule.isStopped) { | ||
| 501 | + var bsize = totalLength > blockSize ? blockSize : totalLength; | ||
| 502 | + await playerModule.feedUint8FromStream( | ||
| 503 | + buffer.sublist(lnData, lnData + bsize)); // await !!!! | ||
| 504 | + lnData += bsize; | ||
| 505 | + totalLength -= bsize; | ||
| 506 | + } | ||
| 507 | + } | ||
| 508 | + | ||
| 509 | + Future<void> startPlayer() async { | ||
| 510 | + try { | ||
| 511 | + Uint8List? dataBuffer; | ||
| 512 | + String? audioFilePath; | ||
| 513 | + var codec = _codec; | ||
| 514 | + if (_media == Media.asset) { | ||
| 515 | + dataBuffer = (await rootBundle.load(assetSample[codec.index])) | ||
| 516 | + .buffer | ||
| 517 | + .asUint8List(); | ||
| 518 | + } else if (_media == Media.file || _media == Media.stream) { | ||
| 519 | + // Do we want to play from buffer or from file ? | ||
| 520 | + if (kIsWeb || await fileExists(_path[codec.index]!)) { | ||
| 521 | + audioFilePath = _path[codec.index]; | ||
| 522 | + } | ||
| 523 | + } else if (_media == Media.buffer) { | ||
| 524 | + // Do we want to play from buffer or from file ? | ||
| 525 | + if (await fileExists(_path[codec.index]!)) { | ||
| 526 | + dataBuffer = await makeBuffer(_path[codec.index]!); | ||
| 527 | + if (dataBuffer == null) { | ||
| 528 | + throw Exception('Unable to create the buffer'); | ||
| 529 | + } | ||
| 530 | + } | ||
| 531 | + } else if (_media == Media.remoteExampleFile) { | ||
| 532 | + // We have to play an example audio file loaded via a URL | ||
| 533 | + audioFilePath = remoteSample[_codec.index]; | ||
| 534 | + } | ||
| 535 | + | ||
| 536 | + if (_media == Media.stream) { | ||
| 537 | + await playerModule.startPlayerFromStream( | ||
| 538 | + codec: Codec.pcm16, //_codec, | ||
| 539 | + numChannels: cstCHANNELNB, | ||
| 540 | + sampleRate: cstSAMPLERATE, // tSTREAMSAMPLERATE, //tSAMPLERATE, | ||
| 541 | + interleaved: true, | ||
| 542 | + bufferSize: 1024, | ||
| 543 | + ); | ||
| 544 | + _addListeners(); | ||
| 545 | + setState(() {}); | ||
| 546 | + await feedHim(audioFilePath!); | ||
| 547 | + //await finishPlayer(); | ||
| 548 | + await stopPlayer(); | ||
| 549 | + return; | ||
| 550 | + } else { | ||
| 551 | + if (audioFilePath != null) { | ||
| 552 | + await playerModule.startPlayer( | ||
| 553 | + fromURI: audioFilePath, | ||
| 554 | + codec: codec, | ||
| 555 | + numChannels: cstCHANNELNB, | ||
| 556 | + sampleRate: cstSAMPLERATE, // tSTREAMSAMPLERATE, | ||
| 557 | + whenFinished: () { | ||
| 558 | + playerModule.logger.d('Play finished'); | ||
| 559 | + setState(() {}); | ||
| 560 | + }); | ||
| 561 | + } else if (dataBuffer != null) { | ||
| 562 | + if (codec == Codec.pcm16) { | ||
| 563 | + dataBuffer = await flutterSoundHelper.pcmToWaveBuffer( | ||
| 564 | + inputBuffer: dataBuffer, | ||
| 565 | + numChannels: cstCHANNELNB, | ||
| 566 | + sampleRate: | ||
| 567 | + cstSAMPLERATE, //(_codec == Codec.pcm16 && _media == Media.asset) ? 48000 : cstSAMPLERATE, | ||
| 568 | + ); | ||
| 569 | + codec = Codec.pcm16WAV; | ||
| 570 | + } | ||
| 571 | + await playerModule.startPlayer( | ||
| 572 | + fromDataBuffer: dataBuffer, | ||
| 573 | + sampleRate: cstSAMPLERATE, | ||
| 574 | + numChannels: cstCHANNELNB, | ||
| 575 | + codec: codec, | ||
| 576 | + whenFinished: () { | ||
| 577 | + playerModule.logger.d('Play finished'); | ||
| 578 | + setState(() {}); | ||
| 579 | + }); | ||
| 580 | + } | ||
| 581 | + } | ||
| 582 | + _addListeners(); | ||
| 583 | + setState(() {}); | ||
| 584 | + playerModule.logger.d('<--- startPlayer'); | ||
| 585 | + } on Exception catch (err) { | ||
| 586 | + playerModule.logger.e('error: $err'); | ||
| 587 | + await stopPlayer(); | ||
| 588 | + } | ||
| 589 | + } | ||
| 590 | + | ||
| 591 | + Future<void> stopPlayer() async { | ||
| 592 | + try { | ||
| 593 | + await playerModule.stopPlayer(); | ||
| 594 | + playerModule.logger.d('stopPlayer'); | ||
| 595 | + if (_playerSubscription != null) { | ||
| 596 | + await _playerSubscription!.cancel(); | ||
| 597 | + _playerSubscription = null; | ||
| 598 | + } | ||
| 599 | + sliderCurrentPosition = 0.0; | ||
| 600 | + } on Exception catch (err) { | ||
| 601 | + playerModule.logger.d('error: $err'); | ||
| 602 | + } | ||
| 603 | + setState(() {}); | ||
| 604 | + } | ||
| 605 | + | ||
| 606 | + void pauseResumePlayer() async { | ||
| 607 | + try { | ||
| 608 | + if (playerModule.isPlaying) { | ||
| 609 | + await playerModule.pausePlayer(); | ||
| 610 | + } else { | ||
| 611 | + await playerModule.resumePlayer(); | ||
| 612 | + } | ||
| 613 | + } on Exception catch (err) { | ||
| 614 | + playerModule.logger.e('error: $err'); | ||
| 615 | + } | ||
| 616 | + setState(() {}); | ||
| 617 | + } | ||
| 618 | + | ||
| 619 | + void pauseResumeRecorder() async { | ||
| 620 | + try { | ||
| 621 | + if (recorderModule.isPaused) { | ||
| 622 | + await recorderModule.resumeRecorder(); | ||
| 623 | + } else { | ||
| 624 | + await recorderModule.pauseRecorder(); | ||
| 625 | + assert(recorderModule.isPaused); | ||
| 626 | + } | ||
| 627 | + } on Exception catch (err) { | ||
| 628 | + recorderModule.logger.e('error: $err'); | ||
| 629 | + } | ||
| 630 | + setState(() {}); | ||
| 631 | + } | ||
| 632 | + | ||
| 633 | + Future<void> seekToPlayer(int milliSecs) async { | ||
| 634 | + //playerModule.logger.d('-->seekToPlayer'); | ||
| 635 | + try { | ||
| 636 | + if (playerModule.isPlaying) { | ||
| 637 | + await playerModule.seekToPlayer(Duration(milliseconds: milliSecs)); | ||
| 638 | + } | ||
| 639 | + } on Exception catch (err) { | ||
| 640 | + playerModule.logger.e('error: $err'); | ||
| 641 | + } | ||
| 642 | + setState(() {}); | ||
| 643 | + //playerModule.logger.d('<--seekToPlayer'); | ||
| 644 | + } | ||
| 645 | + | ||
| 646 | + Widget makeDropdowns(BuildContext context) { | ||
| 647 | + final mediaDropdown = Row( | ||
| 648 | + mainAxisAlignment: MainAxisAlignment.start, | ||
| 649 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 650 | + children: <Widget>[ | ||
| 651 | + const Padding( | ||
| 652 | + padding: EdgeInsets.only(right: 16.0), | ||
| 653 | + child: Text('Media:'), | ||
| 654 | + ), | ||
| 655 | + DropdownButton<Media>( | ||
| 656 | + value: _media, | ||
| 657 | + onChanged: (newMedia) { | ||
| 658 | + _media = newMedia; | ||
| 659 | + setState(() {}); | ||
| 660 | + }, | ||
| 661 | + items: const <DropdownMenuItem<Media>>[ | ||
| 662 | + DropdownMenuItem<Media>( | ||
| 663 | + value: Media.file, | ||
| 664 | + child: Text('File'), | ||
| 665 | + ), | ||
| 666 | + DropdownMenuItem<Media>( | ||
| 667 | + value: Media.buffer, | ||
| 668 | + child: Text('Buffer'), | ||
| 669 | + ), | ||
| 670 | + DropdownMenuItem<Media>( | ||
| 671 | + value: Media.asset, | ||
| 672 | + child: Text('Asset'), | ||
| 673 | + ), | ||
| 674 | + DropdownMenuItem<Media>( | ||
| 675 | + value: Media.remoteExampleFile, | ||
| 676 | + child: Text('Remote Example File'), | ||
| 677 | + ), | ||
| 678 | + DropdownMenuItem<Media>( | ||
| 679 | + value: Media.stream, | ||
| 680 | + child: Text('Dart Stream'), | ||
| 681 | + ), | ||
| 682 | + ], | ||
| 683 | + ), | ||
| 684 | + ], | ||
| 685 | + ); | ||
| 686 | + | ||
| 687 | + final codecDropdown = Row( | ||
| 688 | + mainAxisAlignment: MainAxisAlignment.start, | ||
| 689 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 690 | + children: <Widget>[ | ||
| 691 | + const Padding( | ||
| 692 | + padding: EdgeInsets.only(right: 16.0), | ||
| 693 | + child: Text('Codec:'), | ||
| 694 | + ), | ||
| 695 | + DropdownButton<Codec>( | ||
| 696 | + value: _codec, | ||
| 697 | + onChanged: (newCodec) { | ||
| 698 | + setCodec(newCodec!); | ||
| 699 | + _codec = newCodec; | ||
| 700 | + setState(() {}); | ||
| 701 | + }, | ||
| 702 | + items: const <DropdownMenuItem<Codec>>[ | ||
| 703 | + DropdownMenuItem<Codec>( | ||
| 704 | + value: Codec.aacADTS, | ||
| 705 | + child: Text('AAC/ADTS'), | ||
| 706 | + ), | ||
| 707 | + DropdownMenuItem<Codec>( | ||
| 708 | + value: Codec.opusOGG, | ||
| 709 | + child: Text('Opus/OGG'), | ||
| 710 | + ), | ||
| 711 | + DropdownMenuItem<Codec>( | ||
| 712 | + value: Codec.opusCAF, | ||
| 713 | + child: Text('Opus/CAF'), | ||
| 714 | + ), | ||
| 715 | + DropdownMenuItem<Codec>( | ||
| 716 | + value: Codec.mp3, | ||
| 717 | + child: Text('MP3'), | ||
| 718 | + ), | ||
| 719 | + DropdownMenuItem<Codec>( | ||
| 720 | + value: Codec.vorbisOGG, | ||
| 721 | + child: Text('Vorbis/OGG'), | ||
| 722 | + ), | ||
| 723 | + DropdownMenuItem<Codec>( | ||
| 724 | + value: Codec.pcm16, | ||
| 725 | + child: Text('PCM16'), | ||
| 726 | + ), | ||
| 727 | + DropdownMenuItem<Codec>( | ||
| 728 | + value: Codec.pcm16WAV, | ||
| 729 | + child: Text('PCM16/WAV'), | ||
| 730 | + ), | ||
| 731 | + DropdownMenuItem<Codec>( | ||
| 732 | + value: Codec.pcm16AIFF, | ||
| 733 | + child: Text('PCM16/AIFF'), | ||
| 734 | + ), | ||
| 735 | + DropdownMenuItem<Codec>( | ||
| 736 | + value: Codec.pcm16CAF, | ||
| 737 | + child: Text('PCM16/CAF'), | ||
| 738 | + ), | ||
| 739 | + DropdownMenuItem<Codec>( | ||
| 740 | + value: Codec.flac, | ||
| 741 | + child: Text('FLAC'), | ||
| 742 | + ), | ||
| 743 | + DropdownMenuItem<Codec>( | ||
| 744 | + value: Codec.aacMP4, | ||
| 745 | + child: Text('AAC/MP4'), | ||
| 746 | + ), | ||
| 747 | + DropdownMenuItem<Codec>( | ||
| 748 | + value: Codec.amrNB, | ||
| 749 | + child: Text('AMR-NB'), | ||
| 750 | + ), | ||
| 751 | + DropdownMenuItem<Codec>( | ||
| 752 | + value: Codec.amrWB, | ||
| 753 | + child: Text('AMR-WB '), | ||
| 754 | + ), | ||
| 755 | + DropdownMenuItem<Codec>( | ||
| 756 | + value: Codec.pcm8, | ||
| 757 | + child: Text('PCM8 '), | ||
| 758 | + ), | ||
| 759 | + DropdownMenuItem<Codec>( | ||
| 760 | + value: Codec.pcmFloat32, | ||
| 761 | + child: Text('PCM Float32 '), | ||
| 762 | + ), | ||
| 763 | + DropdownMenuItem<Codec>( | ||
| 764 | + value: Codec.pcmWebM, | ||
| 765 | + child: Text('PCM/WebM '), | ||
| 766 | + ), | ||
| 767 | + DropdownMenuItem<Codec>( | ||
| 768 | + value: Codec.opusWebM, | ||
| 769 | + child: Text('Opus/WebM '), | ||
| 770 | + ), | ||
| 771 | + DropdownMenuItem<Codec>( | ||
| 772 | + value: Codec.vorbisWebM, | ||
| 773 | + child: Text('Vorbis/WebM '), | ||
| 774 | + ), | ||
| 775 | + DropdownMenuItem<Codec>( | ||
| 776 | + value: Codec.pcmFloat32WAV, | ||
| 777 | + child: Text('PCM Float32/WAV'), | ||
| 778 | + ), | ||
| 779 | + ], | ||
| 780 | + ), | ||
| 781 | + ], | ||
| 782 | + ); | ||
| 783 | + | ||
| 784 | + return Padding( | ||
| 785 | + padding: const EdgeInsets.all(8.0), | ||
| 786 | + child: Column( | ||
| 787 | + mainAxisAlignment: MainAxisAlignment.start, | ||
| 788 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 789 | + children: <Widget>[ | ||
| 790 | + Padding( | ||
| 791 | + padding: const EdgeInsets.only(bottom: 16.0), | ||
| 792 | + child: mediaDropdown, | ||
| 793 | + ), | ||
| 794 | + codecDropdown, | ||
| 795 | + ], | ||
| 796 | + ), | ||
| 797 | + ); | ||
| 798 | + } | ||
| 799 | + | ||
| 800 | + void Function()? onPauseResumePlayerPressed() { | ||
| 801 | + if (playerModule.isPaused || playerModule.isPlaying) { | ||
| 802 | + return pauseResumePlayer; | ||
| 803 | + } | ||
| 804 | + return null; | ||
| 805 | + } | ||
| 806 | + | ||
| 807 | + void Function()? onPauseResumeRecorderPressed() { | ||
| 808 | + if (recorderModule.isPaused || recorderModule.isRecording) { | ||
| 809 | + return pauseResumeRecorder; | ||
| 810 | + } | ||
| 811 | + return null; | ||
| 812 | + } | ||
| 813 | + | ||
| 814 | + void Function()? onStopPlayerPressed() { | ||
| 815 | + return (playerModule.isPlaying || playerModule.isPaused) | ||
| 816 | + ? stopPlayer | ||
| 817 | + : null; | ||
| 818 | + } | ||
| 819 | + | ||
| 820 | + void Function()? onStartPlayerPressed() { | ||
| 821 | + if (_media == Media.buffer && kIsWeb) { | ||
| 822 | + return null; | ||
| 823 | + } | ||
| 824 | + if (_media == Media.file || | ||
| 825 | + _media == Media.stream || | ||
| 826 | + _media == Media.buffer) // A file must be already recorded to play it | ||
| 827 | + { | ||
| 828 | + if (_path[_codec.index] == null) return null; | ||
| 829 | + } | ||
| 830 | + | ||
| 831 | + if (_media == Media.stream && _codec != Codec.pcm16) { | ||
| 832 | + return null; | ||
| 833 | + } | ||
| 834 | + | ||
| 835 | + // Disable the button if the selected codec is not supported | ||
| 836 | + if (!(_decoderSupported || | ||
| 837 | + _codec == Codec.pcm16 || | ||
| 838 | + _codec == Codec.pcmFloat32)) { | ||
| 839 | + return null; | ||
| 840 | + } | ||
| 841 | + | ||
| 842 | + return (playerModule.isStopped) ? startPlayer : null; | ||
| 843 | + } | ||
| 844 | + | ||
| 845 | + void startStopRecorder() { | ||
| 846 | + if (recorderModule.isRecording || recorderModule.isPaused) { | ||
| 847 | + stopRecorder(); | ||
| 848 | + } else { | ||
| 849 | + startRecorder(); | ||
| 850 | + } | ||
| 851 | + } | ||
| 852 | + | ||
| 853 | + void Function()? onStartRecorderPressed() { | ||
| 854 | + // Disable the button if the selected codec is not supported | ||
| 855 | + if (!_encoderSupported!) return null; | ||
| 856 | + if (_media == Media.stream && _codec != Codec.pcm16) return null; | ||
| 857 | + return startStopRecorder; | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + AssetImage recorderAssetImage() { | ||
| 861 | + if (onStartRecorderPressed() == null) { | ||
| 862 | + return const AssetImage('res/icons/ic_mic_disabled.png'); | ||
| 863 | + } | ||
| 864 | + return (recorderModule.isStopped) | ||
| 865 | + ? const AssetImage('res/icons/ic_mic.png') | ||
| 866 | + : const AssetImage('res/icons/ic_stop.png'); | ||
| 867 | + } | ||
| 868 | + | ||
| 869 | + Future<void> setCodec(Codec codec) async { | ||
| 870 | + _encoderSupported = await recorderModule.isEncoderSupported(codec); | ||
| 871 | + _decoderSupported = await playerModule.isDecoderSupported(codec); | ||
| 872 | + | ||
| 873 | + setState(() { | ||
| 874 | + _codec = codec; | ||
| 875 | + }); | ||
| 876 | + } | ||
| 877 | + | ||
| 878 | + @override | ||
| 879 | + Widget build(BuildContext context) { | ||
| 880 | + final dropdowns = makeDropdowns(context); | ||
| 881 | + | ||
| 882 | + Widget recorderSection = Column( | ||
| 883 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 884 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 885 | + children: <Widget>[ | ||
| 886 | + Container( | ||
| 887 | + margin: const EdgeInsets.only(top: 12.0, bottom: 16.0), | ||
| 888 | + child: Text( | ||
| 889 | + _recorderTxt, | ||
| 890 | + style: const TextStyle( | ||
| 891 | + fontSize: 35.0, | ||
| 892 | + color: Colors.black, | ||
| 893 | + ), | ||
| 894 | + ), | ||
| 895 | + ), | ||
| 896 | + _isRecording | ||
| 897 | + ? LinearProgressIndicator( | ||
| 898 | + value: 100.0 / 160.0 * (_dbLevel ?? 1) / 100, | ||
| 899 | + valueColor: | ||
| 900 | + const AlwaysStoppedAnimation<Color>(Colors.indigo), | ||
| 901 | + backgroundColor: Colors.limeAccent) | ||
| 902 | + : Container(), | ||
| 903 | + Row( | ||
| 904 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 905 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 906 | + children: <Widget>[ | ||
| 907 | + SizedBox( | ||
| 908 | + width: 56.0, | ||
| 909 | + height: 50.0, | ||
| 910 | + child: ClipOval( | ||
| 911 | + child: TextButton( | ||
| 912 | + onPressed: onStartRecorderPressed(), | ||
| 913 | + //padding: EdgeInsets.all(8.0), | ||
| 914 | + child: Image( | ||
| 915 | + image: recorderAssetImage(), | ||
| 916 | + ), | ||
| 917 | + ), | ||
| 918 | + ), | ||
| 919 | + ), | ||
| 920 | + SizedBox( | ||
| 921 | + width: 56.0, | ||
| 922 | + height: 50.0, | ||
| 923 | + child: ClipOval( | ||
| 924 | + child: TextButton( | ||
| 925 | + onPressed: onPauseResumeRecorderPressed(), | ||
| 926 | + //disabledColor: Colors.white, | ||
| 927 | + //padding: EdgeInsets.all(8.0), | ||
| 928 | + child: Image( | ||
| 929 | + width: 36.0, | ||
| 930 | + height: 36.0, | ||
| 931 | + image: AssetImage(onPauseResumeRecorderPressed() != null | ||
| 932 | + ? 'res/icons/ic_pause.png' | ||
| 933 | + : 'res/icons/ic_pause_disabled.png'), | ||
| 934 | + ), | ||
| 935 | + ), | ||
| 936 | + ), | ||
| 937 | + ), | ||
| 938 | + ], | ||
| 939 | + ), | ||
| 940 | + ]); | ||
| 941 | + | ||
| 942 | + Widget playerSection = Column( | ||
| 943 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 944 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 945 | + children: <Widget>[ | ||
| 946 | + Container( | ||
| 947 | + margin: const EdgeInsets.only(top: 12.0, bottom: 16.0), | ||
| 948 | + child: Text( | ||
| 949 | + _playerTxt, | ||
| 950 | + style: const TextStyle( | ||
| 951 | + fontSize: 35.0, | ||
| 952 | + color: Colors.black, | ||
| 953 | + ), | ||
| 954 | + ), | ||
| 955 | + ), | ||
| 956 | + Row( | ||
| 957 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 958 | + crossAxisAlignment: CrossAxisAlignment.center, | ||
| 959 | + children: <Widget>[ | ||
| 960 | + SizedBox( | ||
| 961 | + width: 56.0, | ||
| 962 | + height: 50.0, | ||
| 963 | + child: ClipOval( | ||
| 964 | + child: TextButton( | ||
| 965 | + onPressed: onStartPlayerPressed(), | ||
| 966 | + //disabledColor: Colors.white, | ||
| 967 | + //padding: EdgeInsets.all(8.0), | ||
| 968 | + child: Image( | ||
| 969 | + image: AssetImage(onStartPlayerPressed() != null | ||
| 970 | + ? 'res/icons/ic_play.png' | ||
| 971 | + : 'res/icons/ic_play_disabled.png'), | ||
| 972 | + ), | ||
| 973 | + ), | ||
| 974 | + ), | ||
| 975 | + ), | ||
| 976 | + SizedBox( | ||
| 977 | + width: 56.0, | ||
| 978 | + height: 50.0, | ||
| 979 | + child: ClipOval( | ||
| 980 | + child: TextButton( | ||
| 981 | + onPressed: onPauseResumePlayerPressed(), | ||
| 982 | + //disabledColor: Colors.white, | ||
| 983 | + //padding: EdgeInsets.all(8.0), | ||
| 984 | + child: Image( | ||
| 985 | + width: 36.0, | ||
| 986 | + height: 36.0, | ||
| 987 | + image: AssetImage(onPauseResumePlayerPressed() != null | ||
| 988 | + ? 'res/icons/ic_pause.png' | ||
| 989 | + : 'res/icons/ic_pause_disabled.png'), | ||
| 990 | + ), | ||
| 991 | + ), | ||
| 992 | + ), | ||
| 993 | + ), | ||
| 994 | + SizedBox( | ||
| 995 | + width: 56.0, | ||
| 996 | + height: 50.0, | ||
| 997 | + child: ClipOval( | ||
| 998 | + child: TextButton( | ||
| 999 | + onPressed: onStopPlayerPressed(), | ||
| 1000 | + //disabledColor: Colors.white, | ||
| 1001 | + //padding: EdgeInsets.all(8.0), | ||
| 1002 | + child: Image( | ||
| 1003 | + width: 28.0, | ||
| 1004 | + height: 28.0, | ||
| 1005 | + image: AssetImage(onStopPlayerPressed() != null | ||
| 1006 | + ? 'res/icons/ic_stop.png' | ||
| 1007 | + : 'res/icons/ic_stop_disabled.png'), | ||
| 1008 | + ), | ||
| 1009 | + ), | ||
| 1010 | + ), | ||
| 1011 | + ), | ||
| 1012 | + ], | ||
| 1013 | + ), | ||
| 1014 | + SizedBox( | ||
| 1015 | + height: 30.0, | ||
| 1016 | + child: Slider( | ||
| 1017 | + value: min(sliderCurrentPosition, maxDuration), | ||
| 1018 | + min: 0.0, | ||
| 1019 | + max: maxDuration, | ||
| 1020 | + onChanged: (value) async { | ||
| 1021 | + await seekToPlayer(value.toInt()); | ||
| 1022 | + }, | ||
| 1023 | + divisions: maxDuration == 0.0 ? 1 : maxDuration.toInt())), | ||
| 1024 | + ], | ||
| 1025 | + ); | ||
| 1026 | + | ||
| 1027 | + return Scaffold( | ||
| 1028 | + appBar: AppBar( | ||
| 1029 | + title: const Text('Flutter Sound Demo'), | ||
| 1030 | + ), | ||
| 1031 | + body: ListView( | ||
| 1032 | + children: <Widget>[ | ||
| 1033 | + recorderSection, | ||
| 1034 | + playerSection, | ||
| 1035 | + dropdowns, | ||
| 1036 | + ], | ||
| 1037 | + ), | ||
| 1038 | + ); | ||
| 1039 | + } | ||
| 1040 | +} |
-
Please register or login to post a comment