|
|
@@ -0,0 +1,216 @@
|
|
|
+import 'package:common_pub/model/distance.dart';
|
|
|
+import 'package:common_pub/model/position.dart' as m;
|
|
|
+import 'package:track_common/widget/prelude.dart';
|
|
|
+
|
|
|
+import '../../../utils.dart';
|
|
|
+import '../../../widget.dart';
|
|
|
+import '../../../widget/app_net_image.dart';
|
|
|
+
|
|
|
+export 'package:common_pub/model/distance.dart';
|
|
|
+
|
|
|
+class MapInfo {
|
|
|
+ const MapInfo(this.id, this.name, this.distance, this.url, this.description,
|
|
|
+ this.mapScaleNumber, this.md5);
|
|
|
+ final int id;
|
|
|
+ final String name;
|
|
|
+ final Distance? distance;
|
|
|
+ final String url;
|
|
|
+ final String description;
|
|
|
+ final int mapScaleNumber;
|
|
|
+ final List<int> md5;
|
|
|
+}
|
|
|
+
|
|
|
+abstract class MapPageController extends GetxController {
|
|
|
+ @override
|
|
|
+ void onInit() {
|
|
|
+ super.onInit();
|
|
|
+ mapGetMore();
|
|
|
+ }
|
|
|
+
|
|
|
+ Future<List<MapInfo>> getMapList(int limit, int offset);
|
|
|
+
|
|
|
+ int get selectedMapId;
|
|
|
+
|
|
|
+ set selectedMap(MapInfo map);
|
|
|
+
|
|
|
+ Future<void> mapGetMore() async {
|
|
|
+ if (isMapGetMoreLoading.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ isMapGetMoreLoading.value = true;
|
|
|
+ await tryApi(() async {
|
|
|
+ final r = await getMapList(20, mapList.length);
|
|
|
+ mapList.addAll(r);
|
|
|
+ return;
|
|
|
+ }, onFinally: () {
|
|
|
+ isMapGetMoreLoading.value = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ mapListScrollController.addListener(() {
|
|
|
+ if (mapListScrollController.position.pixels ==
|
|
|
+ mapListScrollController.position.maxScrollExtent) {
|
|
|
+ //达到最大滚动位置
|
|
|
+ mapGetMore();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ final mapList = <MapInfo>[].obs;
|
|
|
+ final isMapGetMoreLoading = false.obs;
|
|
|
+ final mapListScrollController = ScrollController();
|
|
|
+ final Rx<m.Position?> position = Rx(null);
|
|
|
+}
|
|
|
+
|
|
|
+class MapPage extends GetView<MapPageController> {
|
|
|
+ const MapPage({super.key});
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return Container(
|
|
|
+ width: double.infinity,
|
|
|
+ height: double.infinity,
|
|
|
+ margin: const EdgeInsets.all(20),
|
|
|
+ padding: const EdgeInsets.fromLTRB(58, 28, 58, 28),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Colors.white, borderRadius: BorderRadius.circular(16)),
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ const Row(
|
|
|
+ children: [
|
|
|
+ TitlePoint(),
|
|
|
+ Text(' 地图列表'),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ Expanded(
|
|
|
+ child: Obx(() => GridView.builder(
|
|
|
+ itemCount: controller.mapList.length,
|
|
|
+ controller: controller.mapListScrollController,
|
|
|
+ scrollDirection: Axis.horizontal,
|
|
|
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
+ //设置列数
|
|
|
+ crossAxisCount: 2,
|
|
|
+ //设置横向间距
|
|
|
+ crossAxisSpacing: 10,
|
|
|
+ //设置主轴间距
|
|
|
+ mainAxisSpacing: 10,
|
|
|
+ childAspectRatio: 1.3),
|
|
|
+ itemBuilder: (context, i) {
|
|
|
+ return Obx(() {
|
|
|
+ final data = controller.mapList[i];
|
|
|
+ final s = controller.selectedMapId == data.id;
|
|
|
+ return GalleryCardWidget(
|
|
|
+ data: data,
|
|
|
+ position: controller.position.value,
|
|
|
+ isSelected: s);
|
|
|
+ });
|
|
|
+ })))
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class GalleryCardWidget extends GetView<MapPageController> {
|
|
|
+ final MapInfo data;
|
|
|
+ final m.Position? position;
|
|
|
+ final bool isSelected;
|
|
|
+
|
|
|
+ const GalleryCardWidget(
|
|
|
+ {super.key,
|
|
|
+ required this.data,
|
|
|
+ required this.position,
|
|
|
+ required this.isSelected});
|
|
|
+
|
|
|
+ void onTap(MapInfo mapInfo) {
|
|
|
+ controller.selectedMap = mapInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ var distance = '--';
|
|
|
+ if (data.distance != null) {
|
|
|
+ distance = data.distance!.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () => onTap(data),
|
|
|
+ child: Card(
|
|
|
+ color: Colors.white,
|
|
|
+ shadowColor: isSelected ? Colors.red : null,
|
|
|
+ surfaceTintColor: Colors.white,
|
|
|
+ shape: const RoundedRectangleBorder(
|
|
|
+ borderRadius: BorderRadius.all(Radius.circular(5.44))),
|
|
|
+ clipBehavior: Clip.antiAlias,
|
|
|
+ elevation: isSelected ? 8 : 4,
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ AspectRatio(
|
|
|
+ aspectRatio: 1.1,
|
|
|
+ child: AppNetImage(
|
|
|
+ netImage: NetImage(url: data.url, md5: data.md5),
|
|
|
+ fit: BoxFit.fitHeight)),
|
|
|
+ Expanded(
|
|
|
+ child: Padding(
|
|
|
+ padding: const EdgeInsets.all(6),
|
|
|
+ child: Column(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ data.name,
|
|
|
+ style: const TextStyle(
|
|
|
+ fontSize: 13.5,
|
|
|
+ fontWeight: FontWeight.w500,
|
|
|
+ ),
|
|
|
+ textAlign: TextAlign.start,
|
|
|
+ maxLines: 1,
|
|
|
+ overflow: TextOverflow.ellipsis,
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ data.description,
|
|
|
+ style: const TextStyle(
|
|
|
+ fontSize: 10,
|
|
|
+ color: Color(0xffc6c6c6),
|
|
|
+ ),
|
|
|
+ textAlign: TextAlign.start,
|
|
|
+ maxLines: 1,
|
|
|
+ overflow: TextOverflow.ellipsis,
|
|
|
+ ),
|
|
|
+ const Spacer(),
|
|
|
+ DefaultTextStyle(
|
|
|
+ style: const TextStyle(
|
|
|
+ color: Colors.black, fontSize: 10),
|
|
|
+ child: Row(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.end,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: [
|
|
|
+ Image.asset(Assets.imagesIcMapScale,
|
|
|
+ package: package, height: 9.6),
|
|
|
+ Text(' 1:${data.mapScaleNumber}'),
|
|
|
+ const Spacer(),
|
|
|
+ Image.asset(Assets.imagesIcLocation,
|
|
|
+ package: package, height: 9.6),
|
|
|
+ Text(' $distance'),
|
|
|
+ ],
|
|
|
+ ))
|
|
|
+ ],
|
|
|
+ ))),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget wImage() {
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ SizedBox(
|
|
|
+ height: double.infinity,
|
|
|
+ child: AppNetImage(
|
|
|
+ netImage: NetImage(url: data.url, md5: data.md5),
|
|
|
+ fit: BoxFit.fitHeight)),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|