image_viewer_page.dart 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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(
  77. minScale: PhotoViewComputedScale.contained,
  78. maxScale: PhotoViewComputedScale.covered * 2,
  79. imageProvider: controller.getImageProvider(
  80. controller.imageViewerItemList[index],
  81. ),
  82. initialScale: PhotoViewComputedScale.contained * 0.8,
  83. );
  84. },
  85. backgroundDecoration: BoxDecoration(color: ColorName.black),
  86. pageController: controller.pageController,
  87. );
  88. }),
  89. // 指示器
  90. Visibility(
  91. visible: false,
  92. child: Positioned(
  93. left: 0,
  94. right: 0,
  95. bottom: 40.h,
  96. child: Obx(() {
  97. return _buildIndicator();
  98. }),
  99. ),
  100. ),
  101. // 标题栏
  102. Positioned(
  103. left: 0,
  104. top: 0,
  105. right: 0,
  106. child: Column(children: [_buildStatusBar(), _buildTitleBar()]),
  107. ),
  108. ],
  109. ),
  110. );
  111. }
  112. /// 指示器
  113. Widget _buildIndicator() {
  114. return Center(
  115. child: Row(
  116. mainAxisSize: MainAxisSize.min,
  117. children: [
  118. Text(
  119. '${controller.currentIndex.value + 1}/${controller.imageViewerItemList.length}',
  120. style: TextStyle(
  121. color: Colors.white,
  122. fontSize: 18.sp,
  123. fontWeight: FontWeight.w500,
  124. ),
  125. ),
  126. ],
  127. ),
  128. );
  129. }
  130. /// 状态栏占位
  131. Widget _buildStatusBar() {
  132. double statusBarHeight = MediaQuery.of(Get.context!).padding.top;
  133. return Container(
  134. // 导航栏高度
  135. height: statusBarHeight,
  136. color: backgroundColor(),
  137. );
  138. }
  139. /// 标题栏
  140. Widget _buildTitleBar() {
  141. return Container(
  142. height: kToolbarHeight,
  143. // 宽度,匹配父组件
  144. width: double.infinity,
  145. color: ColorName.black,
  146. padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 14.0),
  147. child: Stack(
  148. children: [
  149. // 返回按钮
  150. GestureDetector(
  151. onTap: controller.clickBack,
  152. child: Assets.images.iconImageViewerClose.image(
  153. width: 24.w,
  154. height: 24.h,
  155. ),
  156. ),
  157. // 标题
  158. Positioned(
  159. left: 0,
  160. top: 0,
  161. right: 0,
  162. child: Container(
  163. alignment: Alignment.center,
  164. child: Text(
  165. StringName.preview,
  166. style: TextStyle(
  167. fontSize: 16.sp,
  168. fontWeight: FontWeight.w500,
  169. color: ColorName.white,
  170. ),
  171. ),
  172. ),
  173. ),
  174. ],
  175. ),
  176. );
  177. }
  178. }