common_point_select_address_page.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/src/widgets/framework.dart';
  5. import 'package:flutter_map/flutter_map.dart';
  6. import 'package:flutter_screenutil/flutter_screenutil.dart';
  7. import 'package:get/get.dart';
  8. import 'package:get/get_core/src/get_main.dart';
  9. import 'package:location/base/base_page.dart';
  10. import 'package:location/resource/assets.gen.dart';
  11. import 'package:location/resource/colors.gen.dart';
  12. import 'package:location/resource/string.gen.dart';
  13. import 'package:location/utils/common_expand.dart';
  14. import 'package:sliding_sheet2/sliding_sheet2.dart';
  15. import '../../../router/app_pages.dart';
  16. import '../../../widget/common_view.dart';
  17. import 'common_point_select_address_controller.dart';
  18. class CommonPointSelectAddressPage
  19. extends BasePage<CommonPointSelectAddressController> {
  20. const CommonPointSelectAddressPage({super.key});
  21. static start() {
  22. Get.toNamed(RoutePath.commonPointSelectAddress);
  23. }
  24. @override
  25. bool immersive() {
  26. return true;
  27. }
  28. @override
  29. Widget buildBody(BuildContext context) {
  30. return PopScope(
  31. canPop: false,
  32. onPopInvokedWithResult: (bool didPop, dynamic result) {
  33. if (didPop) {
  34. return;
  35. }
  36. controller.backClick();
  37. },
  38. child: Stack(
  39. children: [
  40. MapWidget(),
  41. buildHeadBgView(),
  42. buildMapLogoView(),
  43. buildLocationFunView(),
  44. buildSlidingSheetView(),
  45. buildToolbarView(),
  46. ],
  47. ),
  48. );
  49. }
  50. Widget buildLocationFunView() {
  51. return Obx(() {
  52. return Positioned(
  53. right: 12.w,
  54. bottom: 0.48.sh + controller.sheetProgress * 0.48.sh,
  55. child: Opacity(
  56. opacity: 1 - controller.sheetProgress,
  57. child: Container(
  58. width: 38.w,
  59. height: 38.w,
  60. decoration: BoxDecoration(
  61. color: ColorName.white,
  62. borderRadius: BorderRadius.circular(10.r),
  63. boxShadow: [
  64. BoxShadow(
  65. color: ColorName.black10,
  66. blurRadius: 16,
  67. spreadRadius: 2,
  68. offset: Offset(0, 4.w),
  69. ),
  70. ],
  71. ),
  72. child: Center(
  73. child: Assets.images.iconCurrentLocation
  74. .image(width: 20.w, height: 20.w),
  75. )),
  76. ),
  77. );
  78. });
  79. }
  80. Widget buildMapLogoView() {
  81. return Visibility(
  82. visible: Platform.isAndroid,
  83. child: Obx(() {
  84. return Positioned(
  85. left: 12.w,
  86. bottom: 0.465.sh + controller.sheetProgress * 0.48.sh,
  87. child: Opacity(
  88. opacity: 1 - controller.sheetProgress,
  89. child: Column(
  90. crossAxisAlignment: CrossAxisAlignment.start,
  91. children: [
  92. Assets.images.iconAmapLogo.image(height: 20.w),
  93. Text(StringName.locationAmapCo,
  94. style: TextStyle(
  95. fontSize: 9.sp, color: '#666666'.color, height: 1))
  96. ],
  97. ),
  98. ));
  99. }),
  100. );
  101. }
  102. Widget buildSlidingSheetView() {
  103. return SlidingSheet(
  104. listener: (SheetState state) {
  105. controller.setSheetProgress(state.progress);
  106. },
  107. controller: controller.sheetController,
  108. color: ColorName.transparent,
  109. elevation: 0,
  110. shadowColor: ColorName.transparent,
  111. cornerRadius: 0,
  112. snapSpec: SnapSpec(
  113. initialSnap: 0.45,
  114. // Enable snapping. This is true by default.
  115. snap: true,
  116. // Set custom snapping points.
  117. snappings: [0.45, 0.94],
  118. // Define to what the snappings relate to. In this case,
  119. // the total available space that the sheet can expand to.
  120. positioning: SnapPositioning.relativeToAvailableSpace,
  121. ),
  122. headerBuilder: selectAddressHeaderBuilder,
  123. customBuilder: selectAddressCustomBuilder);
  124. }
  125. Widget buildToolbarView() {
  126. return SafeArea(
  127. child: Container(
  128. padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 14.5.w),
  129. child: Row(
  130. children: [
  131. GestureDetector(
  132. onTap: controller.backClick,
  133. child: CommonView.getBackBtnView()),
  134. Spacer(),
  135. Container(
  136. width: 50.w,
  137. height: 28.w,
  138. decoration: BoxDecoration(
  139. color: ColorName.white,
  140. borderRadius: BorderRadius.circular(8.r),
  141. ),
  142. child: Center(
  143. child: Text(StringName.selectAddressDone,
  144. style: TextStyle(
  145. fontSize: 12.sp,
  146. color: ColorName.black90,
  147. fontWeight: FontWeight.bold)),
  148. )),
  149. ],
  150. ),
  151. ),
  152. );
  153. }
  154. Widget buildHeadBgView() {
  155. return IgnorePointer(
  156. child: AspectRatio(
  157. aspectRatio: 360 / 146,
  158. child: Assets.images.bgCommonPointSelectAddressTop.image(
  159. width: double.infinity,
  160. ),
  161. ),
  162. );
  163. }
  164. Widget selectAddressCustomBuilder(BuildContext context,
  165. ScrollController scrollController, SheetState state) {
  166. return ListView.builder(
  167. padding: EdgeInsets.zero,
  168. controller: scrollController,
  169. itemBuilder: (ctx, index) => Text('selectAddressCustomBuilder--$index'),
  170. itemCount: 100,
  171. );
  172. }
  173. Widget selectAddressHeaderBuilder(BuildContext context, SheetState state) {
  174. return IntrinsicHeight(
  175. child: Column(
  176. children: [
  177. buildRangeView(),
  178. SizedBox(height: 12.w),
  179. buildSelectAddressView()
  180. ],
  181. ),
  182. );
  183. }
  184. Widget buildSelectAddressView() {
  185. return GestureDetector(
  186. onTap: controller.onOpenSearchAddressModel,
  187. child: Container(
  188. padding: EdgeInsets.all(12.w),
  189. width: double.infinity,
  190. decoration: BoxDecoration(
  191. color: ColorName.white,
  192. borderRadius: BorderRadius.only(
  193. topLeft: Radius.circular(18.r),
  194. topRight: Radius.circular(18.r))),
  195. child: Obx(() {
  196. return Container(
  197. width: double.infinity,
  198. height: 40.w,
  199. decoration: BoxDecoration(
  200. border: controller.sheetProgress == 1
  201. ? Border.all(color: '#EAECEE'.color, width: 0.5.w)
  202. : null,
  203. color: '#F6F6F8'.color,
  204. borderRadius: BorderRadius.circular(8.r)),
  205. child: Row(
  206. children: [
  207. SizedBox(width: 12.w),
  208. Assets.images.iconCommonPointSearch
  209. .image(width: 14.w, height: 14.w),
  210. SizedBox(width: 6.w),
  211. Expanded(
  212. child: TextField(
  213. enabled: controller.sheetProgress == 1,
  214. controller: controller.searchEditController,
  215. focusNode: controller.searchFocusNode,
  216. style: TextStyle(
  217. fontSize: 14.sp, color: ColorName.primaryTextColor),
  218. maxLines: 1,
  219. maxLength: 30,
  220. keyboardType: TextInputType.text,
  221. textAlignVertical: TextAlignVertical.center,
  222. textInputAction: TextInputAction.next,
  223. decoration: InputDecoration(
  224. hintText:
  225. StringName.selectAddressPleaseEnterPlaceName,
  226. counterText: '',
  227. hintStyle: TextStyle(
  228. fontSize: 13.sp, color: ColorName.black40),
  229. contentPadding: const EdgeInsets.all(0),
  230. border: const OutlineInputBorder(
  231. borderSide: BorderSide.none)))),
  232. SizedBox(width: 12.w),
  233. ],
  234. ),
  235. );
  236. }),
  237. ),
  238. );
  239. }
  240. Widget buildRangeView() {
  241. return Obx(() {
  242. return Opacity(
  243. opacity: 1 - controller.sheetProgress,
  244. child: Container(
  245. width: 336.w,
  246. height: 41.w,
  247. decoration: BoxDecoration(
  248. color: ColorName.white,
  249. borderRadius: BorderRadius.circular(12.r)),
  250. child: Builder(builder: (context) {
  251. return Row(
  252. children: [
  253. SizedBox(width: 16.w),
  254. Text(StringName.selectAddressCommonlyUsedRange,
  255. style:
  256. TextStyle(fontSize: 12.sp, color: ColorName.black80)),
  257. SizedBox(width: 8.w),
  258. Expanded(
  259. child: SliderTheme(
  260. data: SliderTheme.of(context).copyWith(
  261. thumbColor: Colors.white,
  262. thumbShape: CustomBlueThumb(
  263. thumbRadius: 4.6.w,
  264. outerRingWidth: 2.5.w,
  265. color: ColorName.colorPrimary,
  266. ),
  267. overlayShape: SliderComponentShape.noOverlay,
  268. trackHeight: 6.w,
  269. activeTrackColor: ColorName.colorPrimary,
  270. inactiveTrackColor: "#E4E4E4".color,
  271. trackShape: CustomTrackShape(),
  272. ),
  273. child: Obx(() {
  274. return Slider(
  275. value: controller.commonPointRange,
  276. min: 50,
  277. max: 500,
  278. onChanged: (value) {
  279. controller.setCommonPointRange(value);
  280. },
  281. );
  282. }),
  283. ),
  284. ),
  285. SizedBox(width: 8.w),
  286. Container(
  287. width: 48.w,
  288. height: 21.w,
  289. decoration: BoxDecoration(
  290. color: '#F6F6F8'.color,
  291. borderRadius: BorderRadius.circular(5.w)),
  292. child: Center(child: Obx(() {
  293. return Text(
  294. '${controller.commonPointRange.toInt()}m',
  295. style:
  296. TextStyle(fontSize: 12.sp, color: ColorName.black80),
  297. );
  298. })),
  299. ),
  300. SizedBox(width: 16.w),
  301. ],
  302. );
  303. }),
  304. ),
  305. );
  306. });
  307. }
  308. }
  309. class CustomTrackShape extends RoundedRectSliderTrackShape {
  310. @override
  311. Rect getPreferredRect({
  312. required RenderBox parentBox,
  313. Offset offset = Offset.zero,
  314. required SliderThemeData sliderTheme,
  315. bool isEnabled = false,
  316. bool isDiscrete = false,
  317. }) {
  318. final trackHeight = sliderTheme.trackHeight;
  319. final trackLeft = offset.dx;
  320. final trackTop = offset.dy + (parentBox.size.height - trackHeight!) / 2;
  321. final trackWidth = parentBox.size.width;
  322. return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  323. }
  324. }
  325. class CustomBlueThumb extends SliderComponentShape {
  326. final double thumbRadius;
  327. final double outerRingWidth;
  328. final Color color;
  329. const CustomBlueThumb({
  330. this.thumbRadius = 12.0,
  331. this.outerRingWidth = 3.0,
  332. this.color = const Color(0xFF4476FF),
  333. });
  334. @override
  335. Size getPreferredSize(bool isEnabled, bool isDiscrete) {
  336. return Size.fromRadius(thumbRadius + outerRingWidth);
  337. }
  338. @override
  339. void paint(
  340. PaintingContext context,
  341. Offset center, {
  342. required Animation<double> activationAnimation,
  343. required Animation<double> enableAnimation,
  344. required bool isDiscrete,
  345. required TextPainter labelPainter,
  346. required RenderBox parentBox,
  347. required SliderThemeData sliderTheme,
  348. required TextDirection textDirection,
  349. required double value,
  350. required double textScaleFactor,
  351. required Size sizeWithOverflow,
  352. }) {
  353. final Canvas canvas = context.canvas;
  354. final Paint outerPaint = Paint()
  355. ..color = color // 使用您指定的蓝色
  356. ..strokeWidth = outerRingWidth
  357. ..style = PaintingStyle.stroke;
  358. final Paint innerPaint = Paint()
  359. ..color = Colors.white
  360. ..style = PaintingStyle.fill;
  361. // 绘制蓝色外圈
  362. canvas.drawCircle(center, thumbRadius + outerRingWidth / 2, outerPaint);
  363. // 绘制白色内圆
  364. canvas.drawCircle(center, thumbRadius, innerPaint);
  365. }
  366. }