import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:trackoffical_app/generated/assets.dart'; import 'package:trackoffical_app/logger.dart'; import 'package:trackoffical_app/model/m_position.dart'; import 'package:trackoffical_app/model/m_net_image.dart'; import 'package:trackoffical_app/view/home/home_controller.dart'; import 'package:trackoffical_app/pb.dart' as pb; import 'package:trackoffical_app/widget/hard_level.dart'; import '../../widget/app_net_image.dart'; class HomeGalleryView extends GetView { const HomeGalleryView({super.key}); @override Widget build(BuildContext context) { return DefaultTabController( initialIndex: 0, length: 3, child: Scaffold( appBar: _AppBar(), body: Padding( padding: const EdgeInsets.all(12), child: TabBarView( children: [ _TabRecommend(), _TabNearBy(), _TabMy()], )), ), ); } } class _AppBar extends GetView implements PreferredSizeWidget { @override Widget build(BuildContext context) { var theme = Theme.of(context); theme = theme.copyWith( colorScheme: theme.colorScheme.copyWith( surfaceVariant: Colors.transparent, )); return Container( decoration: BoxDecoration( gradient: LinearGradient(colors: [ context.theme.colorScheme.secondary, context.theme.colorScheme.onSecondaryContainer, ]), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), spreadRadius: 3, blurRadius: 5, offset: const Offset(0, 2), // changes position of shadow ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: MediaQuery.of(context).padding.top, ), const Spacer(), SizedBox( width: 240, height: 40, child: Theme( data: theme, child: TabBar( tabs: const [ Tab(text: '推荐'), Tab(text: '附近'), Tab(text: '我的'), ], onTap: (i) { controller.flushGalleryData(); }, labelColor: Colors.white, unselectedLabelColor: Colors.white, labelStyle: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700), unselectedLabelStyle: const TextStyle(fontSize: 14), indicatorColor: Colors.white, ))), ], ), ); } @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); } class _TabMy extends GetView { @override Widget build(BuildContext context) { return Obx(() { final data = controller.galleryData.value.myActivityList; return _dataView(context, data); }); } } class _LocationBar extends GetView { @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(12), child: Obx( () => Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: controller.onClickSelectRegion, child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( controller.regionName ?? '请选择城市', style: const TextStyle(fontSize: 18), ), const Icon(Icons.arrow_drop_down) ], ), ), const Spacer(), _RelocationButton() ]))); } } class _RelocationButton extends GetView { @override Widget build(BuildContext context) { return Obx(() { return SizedBox( width: 80, child: TextButton( onPressed: () => controller.reLocate(), child: Column( mainAxisSize: MainAxisSize.min, children: [ controller.isLocating.value ? Container( height: 18, width: 18, margin: const EdgeInsets.only(bottom: 2), child: CircularProgressIndicator( color: context.theme.colorScheme.primary)) : Image.asset('assets/images/ic_re_location.png', height: 20, color: context.theme.colorScheme.primary), Text(controller.isLocating.value ? '定位中' : '重新定位', style: TextStyle( color: context.theme.colorScheme.primary, fontSize: 13)) ], ), )); }); } } class _TabNearBy extends GetView { @override Widget build(BuildContext context) { return Column( children: [ _LocationBar(), Flexible(child: Obx(() { final data = controller.galleryData.value.nearbyActivityList; return _dataView(context, data); })) ], ); } } class _TabRecommend extends GetView { @override Widget build(BuildContext context) { return Obx(() { final data = controller.galleryData.value.recommendActivityList; return _dataView(context, data); }); } } Widget _dataView(BuildContext context, List data){ return GridView.builder( itemCount: data.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( //设置列数 crossAxisCount: 2, //设置横向间距 crossAxisSpacing: 10, //设置主轴间距 mainAxisSpacing: 10, childAspectRatio: 0.66 ), itemBuilder: (context,i){ return GalleryCardWidget(data: data[i]) ; }); } class GalleryCardWidget extends GetView { final pb.ActivitySimpleInfo data; const GalleryCardWidget({super.key, required this.data}); @override Widget build(BuildContext context) { return GestureDetector( onTap: data.isOpen? () => controller.onClickActivity(data): null, child: Card( color: const Color(0xfff2faff), surfaceTintColor: const Color(0xfff2faff), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(5.44))), clipBehavior: Clip.antiAlias, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AspectRatio( aspectRatio: 1, child: wImage() ), Expanded(child: Padding( padding: const EdgeInsets.all(6), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( data.name, style: const TextStyle( fontSize: 15.24, fontWeight: FontWeight.w500, ), textAlign: TextAlign.start, maxLines: 1, overflow: TextOverflow.ellipsis, ), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ // Image.asset(Assets.imagesIcDistanceStraight, height: 10), const Icon(Icons.location_on, size: 15, color: Colors.grey,), const SizedBox(width: 6), getDistanceText(data), const SizedBox(width: 17), Image.asset(Assets.imagesIcCp, height: 15), const SizedBox(width: 4), Text('${data.totalControlNum}'), ], ), HardLevel(data.difficulty), ], ))) , ], ), ), ); } Widget wImage(){ return Stack( children: [ SizedBox(height: double.infinity,child: AppNetImage( netImage: data.actImage.toModel(), fit: BoxFit.fitHeight)), data.isOpen? const SizedBox(): Container( width: double.infinity, height: double.infinity, color: Colors.white.withAlpha(178), alignment: Alignment.center, child: const Text('待开放', style: TextStyle(color: Color(0xffff6203), fontSize: 15.24),), ) ], ); } Widget getDistanceText(pb.ActivitySimpleInfo data){ return Obx((){ final myPosition = controller.myPosition; var str = ''; if(myPosition != null){ final p = data.position.toModel(); str = p.distance(myPosition).toString(); } return Text(str, style: const TextStyle(color: Colors.grey)); }); } }