home_gallery_view.dart 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:trackoffical_app/generated/assets.dart';
  4. import 'package:trackoffical_app/logger.dart';
  5. import 'package:trackoffical_app/model/m_position.dart';
  6. import 'package:trackoffical_app/model/m_net_image.dart';
  7. import 'package:trackoffical_app/view/home/home_controller.dart';
  8. import 'package:trackoffical_app/pb.dart' as pb;
  9. import 'package:trackoffical_app/widget/hard_level.dart';
  10. import '../../widget/app_net_image.dart';
  11. class HomeGalleryView extends GetView<HomeController> {
  12. const HomeGalleryView({super.key});
  13. @override
  14. Widget build(BuildContext context) {
  15. return DefaultTabController(
  16. initialIndex: 0,
  17. length: 3,
  18. child: Scaffold(
  19. appBar: _AppBar(),
  20. body: Padding(
  21. padding: const EdgeInsets.all(12),
  22. child: TabBarView(
  23. children: [ _TabRecommend(), _TabNearBy(), _TabMy()],
  24. )),
  25. ),
  26. );
  27. }
  28. }
  29. class _AppBar extends GetView<HomeController> implements PreferredSizeWidget {
  30. @override
  31. Widget build(BuildContext context) {
  32. var theme = Theme.of(context);
  33. theme = theme.copyWith(
  34. colorScheme: theme.colorScheme.copyWith(
  35. surfaceVariant: Colors.transparent,
  36. ));
  37. return Container(
  38. decoration: BoxDecoration(
  39. gradient: LinearGradient(colors: [
  40. context.theme.colorScheme.secondary,
  41. context.theme.colorScheme.onSecondaryContainer,
  42. ]),
  43. boxShadow: [
  44. BoxShadow(
  45. color: Colors.grey.withOpacity(0.5),
  46. spreadRadius: 3,
  47. blurRadius: 5,
  48. offset: const Offset(0, 2), // changes position of shadow
  49. ),
  50. ],
  51. ),
  52. child: Column(
  53. crossAxisAlignment: CrossAxisAlignment.start,
  54. children: [
  55. SizedBox(
  56. height: MediaQuery.of(context).padding.top,
  57. ),
  58. const Spacer(),
  59. SizedBox(
  60. width: 240,
  61. height: 40,
  62. child: Theme(
  63. data: theme,
  64. child: TabBar(
  65. tabs: const [
  66. Tab(text: '推荐'),
  67. Tab(text: '附近'),
  68. Tab(text: '我的'),
  69. ],
  70. onTap: (i) {
  71. controller.flushGalleryData();
  72. },
  73. labelColor: Colors.white,
  74. unselectedLabelColor: Colors.white,
  75. labelStyle: const TextStyle(
  76. fontSize: 20, fontWeight: FontWeight.w700),
  77. unselectedLabelStyle: const TextStyle(fontSize: 14),
  78. indicatorColor: Colors.white,
  79. ))),
  80. ],
  81. ),
  82. );
  83. }
  84. @override
  85. Size get preferredSize => const Size.fromHeight(kToolbarHeight);
  86. }
  87. class _TabMy extends GetView<HomeController> {
  88. @override
  89. Widget build(BuildContext context) {
  90. return Obx(() {
  91. final data = controller.galleryData.value.myActivityList;
  92. return _dataView(context, data);
  93. });
  94. }
  95. }
  96. class _LocationBar extends GetView<HomeController> {
  97. @override
  98. Widget build(BuildContext context) {
  99. return Padding(
  100. padding: const EdgeInsets.all(12),
  101. child: Obx(
  102. () => Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
  103. GestureDetector(
  104. onTap: controller.onClickSelectRegion,
  105. child: Row(
  106. mainAxisSize: MainAxisSize.min,
  107. children: [
  108. Text(
  109. controller.regionName ?? '请选择城市',
  110. style: const TextStyle(fontSize: 18),
  111. ),
  112. const Icon(Icons.arrow_drop_down)
  113. ],
  114. ),
  115. ),
  116. const Spacer(),
  117. _RelocationButton()
  118. ])));
  119. }
  120. }
  121. class _RelocationButton extends GetView<HomeController> {
  122. @override
  123. Widget build(BuildContext context) {
  124. return Obx(() {
  125. return SizedBox(
  126. width: 80,
  127. child: TextButton(
  128. onPressed: () => controller.reLocate(),
  129. child: Column(
  130. mainAxisSize: MainAxisSize.min,
  131. children: [
  132. controller.isLocating.value
  133. ? Container(
  134. height: 18,
  135. width: 18,
  136. margin: const EdgeInsets.only(bottom: 2),
  137. child: CircularProgressIndicator(
  138. color: context.theme.colorScheme.primary))
  139. : Image.asset('assets/images/ic_re_location.png',
  140. height: 20, color: context.theme.colorScheme.primary),
  141. Text(controller.isLocating.value ? '定位中' : '重新定位',
  142. style: TextStyle(
  143. color: context.theme.colorScheme.primary, fontSize: 13))
  144. ],
  145. ),
  146. ));
  147. });
  148. }
  149. }
  150. class _TabNearBy extends GetView<HomeController> {
  151. @override
  152. Widget build(BuildContext context) {
  153. return Column(
  154. children: [
  155. _LocationBar(),
  156. Flexible(child: Obx(() {
  157. final data = controller.galleryData.value.nearbyActivityList;
  158. return _dataView(context, data);
  159. }))
  160. ],
  161. );
  162. }
  163. }
  164. class _TabRecommend extends GetView<HomeController> {
  165. @override
  166. Widget build(BuildContext context) {
  167. return Obx(() {
  168. final data = controller.galleryData.value.recommendActivityList;
  169. return _dataView(context, data);
  170. });
  171. }
  172. }
  173. Widget _dataView(BuildContext context, List<pb.ActivitySimpleInfo> data){
  174. return GridView.builder(
  175. itemCount: data.length,
  176. gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
  177. //设置列数
  178. crossAxisCount: 2,
  179. //设置横向间距
  180. crossAxisSpacing: 10,
  181. //设置主轴间距
  182. mainAxisSpacing: 10,
  183. childAspectRatio: 0.66
  184. ),
  185. itemBuilder: (context,i){
  186. return GalleryCardWidget(data: data[i]) ;
  187. });
  188. }
  189. class GalleryCardWidget extends GetView<HomeController> {
  190. final pb.ActivitySimpleInfo data;
  191. const GalleryCardWidget({super.key, required this.data});
  192. @override
  193. Widget build(BuildContext context) {
  194. return GestureDetector(
  195. onTap: data.isOpen? () => controller.onClickActivity(data): null,
  196. child: Card(
  197. color: const Color(0xfff2faff),
  198. surfaceTintColor: const Color(0xfff2faff),
  199. shape: const RoundedRectangleBorder(
  200. borderRadius: BorderRadius.all(Radius.circular(5.44))),
  201. clipBehavior: Clip.antiAlias,
  202. child: Column(
  203. crossAxisAlignment: CrossAxisAlignment.start,
  204. children: [
  205. AspectRatio(
  206. aspectRatio: 1,
  207. child: wImage()
  208. ),
  209. Expanded(child: Padding(
  210. padding: const EdgeInsets.all(6),
  211. child: Column(
  212. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  213. crossAxisAlignment: CrossAxisAlignment.start,
  214. children: [
  215. Text(
  216. data.name,
  217. style: const TextStyle(
  218. fontSize: 15.24,
  219. fontWeight: FontWeight.w500,
  220. ),
  221. textAlign: TextAlign.start,
  222. maxLines: 1,
  223. overflow: TextOverflow.ellipsis,
  224. ),
  225. Row(
  226. crossAxisAlignment: CrossAxisAlignment.center,
  227. children: [
  228. // Image.asset(Assets.imagesIcDistanceStraight, height: 10),
  229. const Icon(Icons.location_on, size: 15, color: Colors.grey,),
  230. const SizedBox(width: 6),
  231. getDistanceText(data),
  232. const SizedBox(width: 17),
  233. Image.asset(Assets.imagesIcCp, height: 15),
  234. const SizedBox(width: 4),
  235. Text('${data.totalControlNum}'),
  236. ],
  237. ),
  238. HardLevel(data.difficulty),
  239. ],
  240. )))
  241. ,
  242. ],
  243. ),
  244. ),
  245. );
  246. }
  247. Widget wImage(){
  248. return Stack(
  249. children: [
  250. SizedBox(height: double.infinity,child: AppNetImage(
  251. netImage: data.actImage.toModel(), fit: BoxFit.fitHeight)),
  252. data.isOpen? const SizedBox():
  253. Container(
  254. width: double.infinity,
  255. height: double.infinity,
  256. color: Colors.white.withAlpha(178),
  257. alignment: Alignment.center,
  258. child: const Text('待开放', style: TextStyle(color: Color(0xffff6203), fontSize: 15.24),),
  259. )
  260. ],
  261. );
  262. }
  263. Widget getDistanceText(pb.ActivitySimpleInfo data){
  264. return Obx((){
  265. final myPosition = controller.myPosition;
  266. var str = '';
  267. if(myPosition != null){
  268. final p = data.position.toModel();
  269. str = p.distance(myPosition).toString();
  270. }
  271. return Text(str, style: const TextStyle(color: Colors.grey));
  272. });
  273. }
  274. }