Open wangzhipeng-vicky opened 5 months ago
8.2.0
Android, iOS
小米9
Flutter version 2.5.1
我是ExtendedImageSlidePage中嵌套ExtendedImageGesturePageView,实现的看大图的需求,就是我手往下滑动大图界面能关掉,没有问题。但是问题是:
`@override Widget build(BuildContext context) { final Size size = MediaQuery.of(context).size; imageDRect = Offset.zero & size;
Widget result = ExtendedImageSlidePage( key: slidePagekey, // slideAxis: SlideAxis.vertical, // slideType: SlideType.wholePage, //在滑动页面的时候根据 Offset 自定义整个页面的背景色 slidePageBackgroundHandler: ( Offset offset, Size pageSize, ) { double opacity = 0.0; // if (pageGestureAxis == SlideAxis.both) { opacity = offset.distance / (Offset(pageSize.width, pageSize.height).distance / 2.0); // } else if (pageGestureAxis == SlideAxis.horizontal) { // opacity = offset.dx.abs() / (pageSize.width / 2.0); // } else if (pageGestureAxis == SlideAxis.vertical) { // opacity = offset.dy.abs() / (pageSize.height / 2.0); // } return const Color(0x00000000) .withOpacity(min(1.0, max(1.0 - opacity, 0.0))); }, //在滑动页面的时候根据 Offset 自定义整个页面的缩放值 slideScaleHandler: ( Offset offset, { ExtendedImageSlidePageState? state, }) { //image is ready and it's not sliding. if (state != null && detailKeys[_currentIndex!] != null && state.scale == 1.0) { //don't slide page if scale of image is more than 1.0 if (state.imageGestureState!.gestureDetails!.totalScale! > 1.0) { return 1.0; } //or slide down into detail mode if (offset.dy < 0 || _imageDetailY < 0) { return 1.0; } } return null; }, //在滑动页面的时候自定义 Offset slideOffsetHandler: ( Offset offset, { ExtendedImageSlidePageState? state, }) { //image is ready and it's not sliding. if (state != null && detailKeys[_currentIndex!] != null && state.scale == 1.0) { //don't slide page if scale of image is more than 1.0 if (state.imageGestureState!.gestureDetails!.totalScale! > 1.0) { return Offset.zero; } //or slide down into detail mode if (offset.dy < 0 || _imageDetailY < 0) { _imageDetailY += offset.dy; // print(offset.dy); _imageDetailY = max( -detailKeys[_currentIndex!]!.maxImageDetailY, _imageDetailY); rebuildDetail.sink.add(_imageDetailY); return Offset.zero; } if (_imageDetailY != 0) { _imageDetailY = 0; _showSwiper = true; rebuildSwiper.add(_showSwiper); rebuildDetail.sink.add(_imageDetailY); } } return null; }, //滑动页面结束的时候计算是否需要 pop 页面 slideEndHandler: ( Offset offset, { ExtendedImageSlidePageState? state, ScaleEndDetails? details, }) { if (_imageDetailY != 0 && state!.scale == 1) { if (!_slideEndAnimationController.isAnimating) {
// get magnitude from gesture velocity final double magnitude = details!.velocity.pixelsPerSecond.distance;
// do a significant magnitude if (magnitude.greaterThanOrEqualTo(minMagnitude)) { final Offset direction = details.velocity.pixelsPerSecond / magnitude * 1000; _slideEndAnimation = _slideEndAnimationController.drive(Tween<double>( begin: _imageDetailY, end: (_imageDetailY + direction.dy) .clamp(-detailKeys[_currentIndex!]!.maxImageDetailY, 0.0), )); _slideEndAnimationController.reset(); _slideEndAnimationController.forward(); } } return false; } return null; }, //滑动页面的回调,你可以在这里改变页面上其他元素的状态 onSlidingPage: (ExtendedImageSlidePageState state) { ///you can change other widgets' state on page as you want ///base on offset/isSliding etc //var offset= state.offset; final bool showSwiper = !state.isSliding; if (showSwiper != _showSwiper) { // do not setState directly here, the image state will change, // you should only notify the widgets which are needed to change // setState(() { // _showSwiper = showSwiper; // }); _showSwiper = showSwiper; rebuildSwiper.add(_showSwiper); } }, child: Material( /// if you use ExtendedImageSlidePage and slideType =SlideType.onlyImage, /// make sure your page is transparent background color: Colors.transparent, // color: Colors.redAccent, shadowColor: Colors.transparent, child: Stack( fit: StackFit.expand, children: <Widget>[ ExtendedImageGesturePageView.builder( controller: ExtendedPageController( initialPage: widget.index!, // pageSpacing: 32,//两个图之间的边距 越大,在A图的右边就能看见B图 2024年5月31日11:18:28 shouldIgnorePointerWhenScrolling: true, ), scrollDirection: Axis.horizontal, // physics: const BouncingScrollPhysics(), //定义PageView的滚动行为 canScrollPage: (GestureDetails? gestureDetails) { return _imageDetailY >= 0; //return (gestureDetails?.totalScale ?? 1.0) <= 1.0; }, itemBuilder: (BuildContext context, int index) { int imageTyep = widget.pics![index].type; late Widget image; Map extendParams = { "fit": BoxFit.contain, "enableSlideOutPage": true, "mode": ExtendedImageMode.gesture, // 手势配置的回调(图片加载完成时).你可以根据图片的信息比如宽高,来初始化 "initGestureConfigHandler": (ExtendedImageState state) { double? initialScale = 1.0; //暂时不要这个了 直接初始默认就是1 而不要计算的,因为对于大图会出现一开始是方法的模式 2024年5月31日10:26:11 if (state.extendedImageInfo != null) { initialScale = initScale( size: size, initialScale: initialScale, imageSize: Size( state.extendedImageInfo!.image.width.toDouble(), state.extendedImageInfo!.image.height .toDouble())); } return GestureConfig( inPageView: true, // initialScale: initialScale!, initialScale: 1, // maxScale: max(initialScale, 5.0), // animationMaxScale: max(initialScale, 5.0), initialAlignment: InitialAlignment.center, minScale: 1.0, //you can cache gesture state even though page view page change. //remember call clearGestureDetailsCache() method at the right time.(for example,this page dispose) cacheGesture: true, ); }, "onDoubleTap": (ExtendedImageGestureState state) { ///you can use define pointerDownPosition as you can, ///default value is double tap pointer down postion. 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]) { end = doubleTapScales[1]; } else { end = doubleTapScales[0]; } _doubleClickAnimationListener = () { //print(_animation.value); state.handleDoubleTap( scale: _doubleClickAnimation!.value, doubleTapPosition: pointerDownPosition); }; _doubleClickAnimation = _doubleClickAnimationController .drive(Tween<double>(begin: begin, end: end)); _doubleClickAnimation! .addListener(_doubleClickAnimationListener); _doubleClickAnimationController.forward(); }, }; if (imageTyep == 0 || imageTyep == 60) { //网络图 final String? originPath = widget.pics![index].originPath; String? demoPath = widget.pics![index].demoPath; String? prePath = widget.pics![index].preViewDemo; String item; if (imageTyep == 60) { item = prePath ?? demoPath!; } else { item = originPath!; } image = createNetworkImage( item, index, extendParams: extendParams, // fit: BoxFit.contain, // enableSlideOutPage: true, // mode: ExtendedImageMode.gesture, loadStateChanged: (ExtendedImageState state) { if (state.extendedImageLoadState == LoadState.completed) { final Rect imageDRect = getDestinationRect( rect: Offset.zero & size, inputSize: Size( state.extendedImageInfo!.image.width.toDouble(), state.extendedImageInfo!.image.height.toDouble(), ), fit: BoxFit.contain, ); detailKeys[index] ??= ImageDetailInfo( imageDRect: imageDRect, pageSize: size, imageInfo: state.extendedImageInfo!, ); final ImageDetailInfo? imageDetailInfo = detailKeys[index]; return StreamBuilder<double>( builder: (BuildContext context, AsyncSnapshot<double> data) { return ExtendedImageGesture( state, canScaleImage: (_) => _imageDetailY == 0, imageBuilder: (Widget image) { return Stack( children: <Widget>[ Positioned.fill( top: _imageDetailY, bottom: -_imageDetailY, child: image, ), Positioned( left: 0.0, right: 0.0, top: imageDetailInfo!.imageBottom + _imageDetailY, child: Opacity( opacity: _imageDetailY == 0 ? 0 : min( 1, _imageDetailY.abs() / (imageDetailInfo .maxImageDetailY / 4.0), ), ), ), ], ); }, ); }, initialData: _imageDetailY, stream: rebuildDetail.stream, ); } else if (state.extendedImageLoadState == LoadState.loading) { return Center( child: Image.asset( "assets/images/loading.gif", width: 40, height: 40, ), ); } else if (state.extendedImageLoadState == LoadState.failed) { return GestureDetector( child: /*Container( color: const Color(0xFFF3F4F5), child:*/ Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( "assets/images/img_load_failed.png", // "assets/images/loading.gif", width: 40, height: 40, ), const Padding( padding: EdgeInsets.only( left: 3, top: 15, right: 3), child: Text( "加载失败,点击重试", style: TextStyle( fontSize: 15, color: Color(0XFF999999)), textAlign: TextAlign.center, ), ) ]), // ), onTap: () { state.reLoadImage(); }, ); } return null; }, ); } else if (imageTyep == 1 || imageTyep == 61) { image = createFileWithWechatPicker( widget.pics![index].entity!, extendParams: extendParams, ); // tag = widget.pics![index].tag; } if (index < min(9, widget.pics!.length)) { image = HeroWidget( tag: widget.pics![index].tag, slideType: SlideType.onlyImage, slidePagekey: slidePagekey, child: image, ); } image = GestureDetector( child: image, onTap: () { if (_imageDetailY != 0) { _imageDetailY = 0; rebuildDetail.sink.add(_imageDetailY); } else { slidePagekey.currentState!.popPage(); Navigator.pop(context); } }, ); return image; }, itemCount: widget.pics!.length, onPageChanged: (int index) { _currentIndex = index; rebuildIndex.add(index); if (_imageDetailY != 0) { _imageDetailY = 0; rebuildDetail.sink.add(_imageDetailY); } _showSwiper = true; rebuildSwiper.add(_showSwiper); _preloadImage(index - 1); _preloadImage(index + 1); }, ), Visibility( visible: !(widget.isOnlyPreview && widget.pics!.length == 1), child: StreamBuilder<bool>( //负责根据不同状态创建对应ui的方法实现 builder: (BuildContext c, AsyncSnapshot<bool> d) { if (d.data == null || !d.data!) { return Container(); } return Positioned( bottom: 0.0, left: 0.0, right: 0.0, child: MySwiperPlugin(widget.pics, _currentIndex, rebuildIndex, widget.operateMenu), ); }, initialData: true, //默认初始化数据 stream: rebuildSwiper .stream, //stream事件流对象 rebuildSwiper.stream获取Stream用作事件监听 )) ], ), )); return result;
}`
No response
623301600@qq.com
Version
8.2.0
Platforms
Android, iOS
Device Model
小米9
flutter info
How to reproduce?
我是ExtendedImageSlidePage中嵌套ExtendedImageGesturePageView,实现的看大图的需求,就是我手往下滑动大图界面能关掉,没有问题。但是问题是:
`@override Widget build(BuildContext context) { final Size size = MediaQuery.of(context).size; imageDRect = Offset.zero & size;
// get magnitude from gesture velocity final double magnitude = details!.velocity.pixelsPerSecond.distance;
}`
Logs
No response
Example code (optional)
No response
Contact
623301600@qq.com