map_page.dart 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import 'package:application/service/map_watch.dart';
  2. import 'package:common_pub/model/distance.dart';
  3. import '../../../service/api.dart' as api;
  4. import '../../../utils.dart';
  5. import 'package:common_pub/model/position.dart' as m;
  6. import '../../../widget.dart';
  7. typedef MapInfo = api.ToMapSimpleV2;
  8. class MapPageController extends GetxController {
  9. @override
  10. void onInit() {
  11. super.onInit();
  12. mapGetMore();
  13. }
  14. Future<void> mapGetMore() async {
  15. if (isMapGetMoreLoading.value) {
  16. return;
  17. }
  18. isMapGetMoreLoading.value = true;
  19. await tryApi(() async {
  20. final r = await api.ApiService.to.stub.toMapListV2(api.MapListRequestV2()
  21. ..limit = 20
  22. ..offset = mapList.length);
  23. mapList.addAll(r.list);
  24. return;
  25. }, onFinally: () {
  26. isMapGetMoreLoading.value = false;
  27. });
  28. mapListScrollController.addListener(() {
  29. if (mapListScrollController.position.pixels ==
  30. mapListScrollController.position.maxScrollExtent) {
  31. //达到最大滚动位置
  32. mapGetMore();
  33. }
  34. });
  35. }
  36. final mapList = <MapInfo>[].obs;
  37. final isMapGetMoreLoading = false.obs;
  38. final mapListScrollController = ScrollController();
  39. final Rx<m.Position?> position = Rx(null);
  40. }
  41. class MapPage extends StatelessWidget {
  42. const MapPage({super.key});
  43. @override
  44. Widget build(BuildContext context) {
  45. return GetBuilder(
  46. init: MapPageController(),
  47. builder: (c) {
  48. return Container(
  49. width: double.infinity,
  50. height: double.infinity,
  51. margin: const EdgeInsets.all(20),
  52. padding: const EdgeInsets.fromLTRB(58, 28, 58, 28),
  53. decoration: BoxDecoration(
  54. color: Colors.white, borderRadius: BorderRadius.circular(16)),
  55. child: Column(
  56. children: [
  57. const Row(
  58. children: [
  59. TitlePoint(),
  60. Text(' 地图列表'),
  61. ],
  62. ),
  63. Expanded(
  64. child: Obx(() => GridView.builder(
  65. itemCount: c.mapList.length,
  66. controller: c.mapListScrollController,
  67. scrollDirection: Axis.horizontal,
  68. gridDelegate:
  69. const SliverGridDelegateWithFixedCrossAxisCount(
  70. //设置列数
  71. crossAxisCount: 2,
  72. //设置横向间距
  73. crossAxisSpacing: 10,
  74. //设置主轴间距
  75. mainAxisSpacing: 10,
  76. childAspectRatio: 1.3),
  77. itemBuilder: (context, i) {
  78. return Obx((){
  79. final data = c.mapList[i];
  80. final id = MapWatchService.instance?.id;
  81. final s = id == MapId(data.mapId);
  82. return GalleryCardWidget(data: data, position: c.position.value, isSelected: s);
  83. }) ;
  84. })))
  85. ],
  86. ),
  87. );
  88. });
  89. }
  90. }
  91. class GalleryCardWidget extends StatelessWidget {
  92. final MapInfo data;
  93. final m.Position? position;
  94. final bool isSelected;
  95. const GalleryCardWidget({
  96. super.key,
  97. required this.data,
  98. required this.position, required this.isSelected});
  99. void onTap(int id) async {
  100. await MapWatchService.setMapById(MapId(id));
  101. }
  102. @override
  103. Widget build(BuildContext context) {
  104. var distance = '--';
  105. if ( data.hasDistance()) {
  106. distance = Distance(m: data.distance).toString();
  107. }
  108. return GestureDetector(
  109. onTap: ()=>onTap(data.mapId),
  110. child: Card(
  111. color: Colors.white,
  112. shadowColor: isSelected? Colors.red: null,
  113. surfaceTintColor: Colors.white,
  114. shape: const RoundedRectangleBorder(
  115. borderRadius: BorderRadius.all(Radius.circular(5.44))),
  116. clipBehavior: Clip.antiAlias,
  117. elevation: isSelected?8:4,
  118. child: Column(
  119. crossAxisAlignment: CrossAxisAlignment.start,
  120. children: [
  121. AspectRatio(aspectRatio: 1.1, child: AppNetImage(netImage: data.image, fit: BoxFit.fitHeight)),
  122. Expanded(
  123. child: Padding(
  124. padding: const EdgeInsets.all(6),
  125. child: Column(
  126. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  127. crossAxisAlignment: CrossAxisAlignment.start,
  128. children: [
  129. Text(
  130. data.name,
  131. style: const TextStyle(
  132. fontSize: 13.5,
  133. fontWeight: FontWeight.w500,
  134. ),
  135. textAlign: TextAlign.start,
  136. maxLines: 1,
  137. overflow: TextOverflow.ellipsis,
  138. ),
  139. Text(
  140. data.description,
  141. style: const TextStyle(
  142. fontSize: 10,
  143. color: Color(0xffc6c6c6),
  144. ),
  145. textAlign: TextAlign.start,
  146. maxLines: 1,
  147. overflow: TextOverflow.ellipsis,
  148. ),
  149. const Spacer(),
  150. DefaultTextStyle(
  151. style: const TextStyle(
  152. color: Colors.black, fontSize: 10),
  153. child: Row(
  154. crossAxisAlignment: CrossAxisAlignment.end,
  155. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  156. children: [
  157. Image.asset(Assets.imagesIcMapScale,
  158. height: 9.6),
  159. Text(' 1:${data.mapScaleNumber}'),
  160. const Spacer(),
  161. Image.asset(Assets.imagesIcLocation,
  162. height: 9.6),
  163. Text(' $distance'),
  164. ],
  165. ))
  166. ],
  167. ))),
  168. ],
  169. ),
  170. ),
  171. );
  172. }
  173. Widget wImage() {
  174. return Stack(
  175. children: [
  176. SizedBox(
  177. height: double.infinity,
  178. child: AppNetImage(netImage: data.image, fit: BoxFit.fitHeight)
  179. ),
  180. ],
  181. );
  182. }
  183. }