diff --git a/lib/pages/dynamics/widgets/pic_panel.dart b/lib/pages/dynamics/widgets/pic_panel.dart index 6fb21b16..25b22c21 100644 --- a/lib/pages/dynamics/widgets/pic_panel.dart +++ b/lib/pages/dynamics/widgets/pic_panel.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/pages/preview/index.dart'; Widget picWidget(item, context) { String type = item.modules.moduleDynamic.major.type; @@ -16,7 +16,7 @@ Widget picWidget(item, context) { pictures = item.modules.moduleDynamic.major.draw.items; } int len = pictures.length; - List picList = []; + List picList = []; List list = []; for (var i = 0; i < len; i++) { picList.add(pictures[i].src ?? pictures[i].url); @@ -25,11 +25,14 @@ Widget picWidget(item, context) { builder: (context, BoxConstraints box) { return GestureDetector( onTap: () { - Get.toNamed('/preview', - arguments: {'initialPage': i, 'imgList': picList}); + showDialog( + useSafeArea: false, + context: context, + builder: (context) { + return ImagePreview(initialPage: i, imgList: picList); + }, + ); }, - // child: Hero( - // tag: pictures[i].src ?? pictures[i].url, child: NetworkImgLayer( src: pictures[i].src ?? pictures[i].url, width: box.maxWidth, diff --git a/lib/pages/preview/controller.dart b/lib/pages/preview/controller.dart index 500f0b1d..bb06b275 100644 --- a/lib/pages/preview/controller.dart +++ b/lib/pages/preview/controller.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:dio/dio.dart'; import 'package:path_provider/path_provider.dart'; @@ -17,17 +18,6 @@ class PreviewController extends GetxController { bool photos = true; String currentImgUrl = ''; - @override - void onInit() { - super.onInit(); - if (Get.arguments != null) { - initialPage.value = Get.arguments['initialPage']!; - currentPage.value = Get.arguments['initialPage']! + 1; - imgList.value = Get.arguments['imgList']; - currentImgUrl = imgList[initialPage.value]; - } - } - requestPermission() async { Map statuses = await [ Permission.storage, @@ -40,10 +30,11 @@ class PreviewController extends GetxController { // 图片分享 void onShareImg() async { - requestPermission(); + SmartDialog.showLoading(); var response = await Dio().get(imgList[initialPage.value], options: Options(responseType: ResponseType.bytes)); final temp = await getTemporaryDirectory(); + SmartDialog.dismiss(); String imgName = "plpl_pic_${DateTime.now().toString().split('-').join()}.jpg"; var path = '${temp.path}/$imgName'; diff --git a/lib/pages/preview/view.dart b/lib/pages/preview/view.dart index 65014aac..22cc8952 100644 --- a/lib/pages/preview/view.dart +++ b/lib/pages/preview/view.dart @@ -15,7 +15,13 @@ import 'package:status_bar_control/status_bar_control.dart'; typedef DoubleClickAnimationListener = void Function(); class ImagePreview extends StatefulWidget { - const ImagePreview({Key? key}) : super(key: key); + final int? initialPage; + final List? imgList; + const ImagePreview({ + Key? key, + this.initialPage, + this.imgList, + }) : super(key: key); @override _ImagePreviewState createState() => _ImagePreviewState(); @@ -34,6 +40,11 @@ class _ImagePreviewState extends State @override void initState() { super.initState(); + + _previewController.initialPage.value = widget.initialPage!; + _previewController.currentPage.value = widget.initialPage! + 1; + _previewController.imgList.value = widget.imgList!; + _previewController.currentImgUrl = widget.imgList![widget.initialPage!]; // animationController = AnimationController( // vsync: this, duration: const Duration(milliseconds: 400)); setStatusBar(); @@ -42,9 +53,8 @@ class _ImagePreviewState extends State } onOpenMenu() { - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, + showDialog( + context: context, builder: (BuildContext context) { return AlertDialog( clipBehavior: Clip.hardEdge, @@ -55,7 +65,7 @@ class _ImagePreviewState extends State ListTile( onTap: () { _previewController.onShareImg(); - SmartDialog.dismiss(); + Get.back(); }, dense: true, title: const Text('分享', style: TextStyle(fontSize: 14)), @@ -65,8 +75,8 @@ class _ImagePreviewState extends State Clipboard.setData( ClipboardData(text: _previewController.currentImgUrl)) .then((value) { + Get.back(); SmartDialog.showToast('已复制到粘贴板'); - SmartDialog.dismiss(); }).catchError((err) { SmartDialog.showNotify( msg: err.toString(), @@ -79,6 +89,7 @@ class _ImagePreviewState extends State ), ListTile( onTap: () { + Get.back(); DownloadUtils.downloadImg(_previewController.currentImgUrl); }, dense: true, @@ -93,13 +104,21 @@ class _ImagePreviewState extends State // 设置状态栏图标透明 setStatusBar() async { - await StatusBarControl.setHidden(true, animation: StatusBarAnimation.SLIDE); + if (Platform.isIOS) { + await StatusBarControl.setHidden(true, + animation: StatusBarAnimation.SLIDE); + } + if (Platform.isAndroid) { + await StatusBarControl.setColor(Colors.transparent); + } } @override void dispose() { // animationController.dispose(); - StatusBarControl.setHidden(false, animation: StatusBarAnimation.SLIDE); + try { + StatusBarControl.setHidden(false, animation: StatusBarAnimation.SLIDE); + } catch (_) {} _doubleClickAnimationController.dispose(); clearGestureDetailsCache(); super.dispose(); @@ -129,109 +148,105 @@ class _ImagePreviewState extends State direction: DismissiblePageDismissDirection.down, disabled: _dismissDisabled, isFullScreen: true, - child: Hero( - tag: _previewController - .imgList[_previewController.initialPage.value], - child: GestureDetector( - onLongPress: () => onOpenMenu(), - child: ExtendedImageGesturePageView.builder( - controller: ExtendedPageController( - initialPage: _previewController.initialPage.value, - pageSpacing: 0, - ), - onPageChanged: (int index) => - _previewController.onChange(index), - canScrollPage: (GestureDetails? gestureDetails) => - gestureDetails!.totalScale! <= 1.0, - preloadPagesCount: 2, - itemCount: _previewController.imgList.length, - itemBuilder: (BuildContext context, int index) { - return ExtendedImage.network( - _previewController.imgList[index], - fit: BoxFit.contain, - mode: ExtendedImageMode.gesture, - onDoubleTap: (ExtendedImageGestureState state) { - final Offset? pointerDownPosition = - state.pointerDownPosition; - final double? begin = state.gestureDetails!.totalScale; - double end; - - //remove old - _doubleClickAnimation - ?.removeListener(_doubleClickAnimationListener); - - //stop pre - _doubleClickAnimationController.stop(); - - //reset to use - _doubleClickAnimationController.reset(); - - if (begin == doubleTapScales[0]) { - setState(() { - _dismissDisabled = true; - }); - end = doubleTapScales[1]; - } else { - setState(() { - _dismissDisabled = false; - }); - end = doubleTapScales[0]; - } - - _doubleClickAnimationListener = () { - state.handleDoubleTap( - scale: _doubleClickAnimation!.value, - doubleTapPosition: pointerDownPosition); - }; - _doubleClickAnimation = _doubleClickAnimationController - .drive(Tween(begin: begin, end: end)); - - _doubleClickAnimation! - .addListener(_doubleClickAnimationListener); - - _doubleClickAnimationController.forward(); - }, - // ignore: body_might_complete_normally_nullable - loadStateChanged: (ExtendedImageState state) { - if (state.extendedImageLoadState == LoadState.loading) { - final ImageChunkEvent? loadingProgress = - state.loadingProgress; - final double? progress = - loadingProgress?.expectedTotalBytes != null - ? loadingProgress!.cumulativeBytesLoaded / - loadingProgress.expectedTotalBytes! - : null; - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: 150.0, - child: LinearProgressIndicator( - value: progress, - color: Colors.white, - ), - ), - const SizedBox(height: 10.0), - Text('${((progress ?? 0.0) * 100).toInt()}%'), - ], - ), - ); - } - }, - initGestureConfigHandler: (ExtendedImageState state) { - return GestureConfig( - inPageView: true, - initialScale: 1.0, - maxScale: 5.0, - animationMaxScale: 6.0, - initialAlignment: InitialAlignment.center, - ); - }, - ); - }, + child: GestureDetector( + onLongPress: () => onOpenMenu(), + child: ExtendedImageGesturePageView.builder( + controller: ExtendedPageController( + initialPage: _previewController.initialPage.value, + pageSpacing: 0, ), + onPageChanged: (int index) => + _previewController.onChange(index), + canScrollPage: (GestureDetails? gestureDetails) => + gestureDetails!.totalScale! <= 1.0, + preloadPagesCount: 2, + itemCount: widget.imgList!.length, + itemBuilder: (BuildContext context, int index) { + return ExtendedImage.network( + widget.imgList![index], + fit: BoxFit.contain, + mode: ExtendedImageMode.gesture, + onDoubleTap: (ExtendedImageGestureState state) { + final Offset? pointerDownPosition = + state.pointerDownPosition; + final double? begin = state.gestureDetails!.totalScale; + double end; + + //remove old + _doubleClickAnimation + ?.removeListener(_doubleClickAnimationListener); + + //stop pre + _doubleClickAnimationController.stop(); + + //reset to use + _doubleClickAnimationController.reset(); + + if (begin == doubleTapScales[0]) { + setState(() { + _dismissDisabled = true; + }); + end = doubleTapScales[1]; + } else { + setState(() { + _dismissDisabled = false; + }); + end = doubleTapScales[0]; + } + + _doubleClickAnimationListener = () { + state.handleDoubleTap( + scale: _doubleClickAnimation!.value, + doubleTapPosition: pointerDownPosition); + }; + _doubleClickAnimation = _doubleClickAnimationController + .drive(Tween(begin: begin, end: end)); + + _doubleClickAnimation! + .addListener(_doubleClickAnimationListener); + + _doubleClickAnimationController.forward(); + }, + // ignore: body_might_complete_normally_nullable + loadStateChanged: (ExtendedImageState state) { + if (state.extendedImageLoadState == LoadState.loading) { + final ImageChunkEvent? loadingProgress = + state.loadingProgress; + final double? progress = + loadingProgress?.expectedTotalBytes != null + ? loadingProgress!.cumulativeBytesLoaded / + loadingProgress.expectedTotalBytes! + : null; + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 150.0, + child: LinearProgressIndicator( + value: progress, + color: Colors.white, + ), + ), + // const SizedBox(height: 10.0), + // Text('${((progress ?? 0.0) * 100).toInt()}%',), + ], + ), + ); + } + }, + initGestureConfigHandler: (ExtendedImageState state) { + return GestureConfig( + inPageView: true, + initialScale: 1.0, + maxScale: 5.0, + animationMaxScale: 6.0, + initialAlignment: InitialAlignment.center, + ); + }, + ); + }, ), ), ), @@ -241,7 +256,7 @@ class _ImagePreviewState extends State bottom: 0, child: Container( padding: EdgeInsets.only( - bottom: MediaQuery.of(context).padding.bottom, top: 20), + bottom: MediaQuery.of(context).padding.bottom + 30), decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, @@ -262,8 +277,7 @@ class _ImagePreviewState extends State TextSpan( text: _previewController.currentPage.toString()), const TextSpan(text: ' / '), - TextSpan( - text: _previewController.imgList.length.toString()), + TextSpan(text: widget.imgList!.length.toString()), ]), ), ), diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index df51b118..fb06ca0a 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -7,6 +7,7 @@ import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/item.dart'; +import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/replyNew/index.dart'; import 'package:pilipala/utils/feed_back.dart'; @@ -773,7 +774,7 @@ InlineSpan buildContent( // 图片渲染 if (content.pictures.isNotEmpty) { - List picList = []; + List picList = []; int len = content.pictures.length; if (len == 1) { Map pictureItem = content.pictures.first; @@ -785,8 +786,13 @@ InlineSpan buildContent( builder: (context, BoxConstraints box) { return GestureDetector( onTap: () { - Get.toNamed('/preview', - arguments: {'initialPage': 0, 'imgList': picList}); + showDialog( + useSafeArea: false, + context: context, + builder: (context) { + return ImagePreview(initialPage: 0, imgList: picList); + }, + ); }, child: Padding( padding: const EdgeInsets.only(top: 4), @@ -814,8 +820,13 @@ InlineSpan buildContent( builder: (context, BoxConstraints box) { return GestureDetector( onTap: () { - Get.toNamed('/preview', - arguments: {'initialPage': i, 'imgList': picList}); + showDialog( + useSafeArea: false, + context: context, + builder: (context) { + return ImagePreview(initialPage: i, imgList: picList); + }, + ); }, child: NetworkImgLayer( src: content.pictures[i]['img_src'],