common_point_select_address_page.dart 11 KB

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