image_viewer_page.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:get/get.dart';
  4. import 'package:keyboard/base/base_page.dart';
  5. import 'package:keyboard/data/bean/image_viewer_item.dart';
  6. import 'package:keyboard/resource/colors.gen.dart';
  7. import 'package:keyboard/resource/string.gen.dart';
  8. import 'package:keyboard/router/app_page_arguments.dart';
  9. import 'package:keyboard/router/app_pages.dart';
  10. import 'package:photo_view/photo_view.dart';
  11. import 'package:photo_view/photo_view_gallery.dart';
  12. import '../../../resource/assets.gen.dart';
  13. import 'image_viewer_controller.dart';
  14. /// 图片预览页
  15. class ImageViewerPage extends BasePage<ImageViewerController> {
  16. const ImageViewerPage({super.key});
  17. /// 跳转
  18. /// [imageViewerItemList] 图片预览数据列表
  19. /// [index] 当前预览的索引,默认为0
  20. static void start(
  21. List<ImageViewerItem> imageViewerItemList, {
  22. int index = 0,
  23. }) {
  24. Map<String, dynamic> args = {
  25. AppPageArguments.imageViewerItemList: imageViewerItemList,
  26. AppPageArguments.index: index,
  27. };
  28. Get.toNamed(RoutePath.imageViewer, arguments: args);
  29. }
  30. @override
  31. backgroundColor() => ColorName.black;
  32. @override
  33. immersive() {
  34. // 沉浸式页面
  35. return true;
  36. }
  37. @override
  38. bool statusBarDarkFont() {
  39. // 状态栏,白色字体
  40. return false;
  41. }
  42. @override
  43. Widget buildBody(BuildContext context) {
  44. return Scaffold(
  45. backgroundColor: backgroundColor(),
  46. body: Stack(
  47. children: [
  48. // 预览图
  49. Obx(() {
  50. return PhotoViewGallery.builder(
  51. // 滚动特性
  52. scrollPhysics: const BouncingScrollPhysics(),
  53. // 页面数量
  54. itemCount: controller.imageViewerItemList.length,
  55. // 禁止旋转
  56. enableRotation: false,
  57. loadingBuilder:
  58. (context, event) => Center(
  59. child: SizedBox(
  60. width: 20.0,
  61. height: 20.0,
  62. child: CircularProgressIndicator(
  63. value:
  64. event == null
  65. ? 0
  66. : event.cumulativeBytesLoaded /
  67. (event.expectedTotalBytes ?? 0),
  68. ),
  69. ),
  70. ),
  71. onPageChanged: (index) {
  72. // 更新当前索引
  73. controller.updateCurrentIndex(index);
  74. },
  75. builder: (BuildContext context, int index) {
  76. return PhotoViewGalleryPageOptions.customChild(
  77. minScale: PhotoViewComputedScale.contained,
  78. maxScale: PhotoViewComputedScale.covered * 2,
  79. initialScale: PhotoViewComputedScale.contained * 0.8,
  80. // 自定义视图
  81. child: _buildImageViewerItem(index),
  82. );
  83. },
  84. // backgroundDecoration: BoxDecoration(color: ColorName.black),
  85. pageController: controller.pageController,
  86. );
  87. }),
  88. // 指示器
  89. Visibility(
  90. visible: false,
  91. child: Positioned(
  92. left: 0,
  93. right: 0,
  94. bottom: 40.h,
  95. child: Obx(() {
  96. return _buildIndicator();
  97. }),
  98. ),
  99. ),
  100. // 标题栏
  101. Positioned(
  102. left: 0,
  103. top: 0,
  104. right: 0,
  105. child: Column(children: [_buildStatusBar(), _buildTitleBar()]),
  106. ),
  107. ],
  108. ),
  109. );
  110. }
  111. /// 构建每一项
  112. Widget _buildImageViewerItem(int index) {
  113. return Stack(
  114. fit: StackFit.expand,
  115. children: [
  116. Image(
  117. image: controller.getImageProvider(
  118. controller.imageViewerItemList[index],
  119. ),
  120. // fit: BoxFit.cover,
  121. ),
  122. ],
  123. );
  124. }
  125. /// 指示器
  126. Widget _buildIndicator() {
  127. return Center(
  128. child: Row(
  129. mainAxisSize: MainAxisSize.min,
  130. children: [
  131. Text(
  132. '${controller.currentIndex.value + 1}/${controller.imageViewerItemList.length}',
  133. style: TextStyle(
  134. color: Colors.white,
  135. fontSize: 18.sp,
  136. fontWeight: FontWeight.w500,
  137. ),
  138. ),
  139. ],
  140. ),
  141. );
  142. }
  143. /// 状态栏占位
  144. Widget _buildStatusBar() {
  145. double statusBarHeight = MediaQuery.of(Get.context!).padding.top;
  146. return Container(
  147. // 导航栏高度
  148. height: statusBarHeight,
  149. color: backgroundColor(),
  150. );
  151. }
  152. /// 标题栏
  153. Widget _buildTitleBar() {
  154. return Container(
  155. height: kToolbarHeight,
  156. // 宽度,匹配父组件
  157. width: double.infinity,
  158. color: ColorName.black,
  159. padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 14.0),
  160. child: Stack(
  161. children: [
  162. // 返回按钮
  163. GestureDetector(
  164. onTap: controller.clickBack,
  165. child: Assets.images.iconImageViewerClose.image(
  166. width: 24.w,
  167. height: 24.h,
  168. ),
  169. ),
  170. // 标题
  171. Positioned(
  172. left: 0,
  173. top: 0,
  174. right: 0,
  175. child: Container(
  176. alignment: Alignment.center,
  177. child: Text(
  178. StringName.preview,
  179. style: TextStyle(
  180. fontSize: 16.sp,
  181. fontWeight: FontWeight.w500,
  182. color: ColorName.white,
  183. ),
  184. ),
  185. ),
  186. ),
  187. ],
  188. ),
  189. );
  190. }
  191. }