flutter中自定义一个点击图片放大的widget
2021-11-19 本文已影响0人
小木虫666
在开发电商app的时候,用户会需要点开查看商品的大图
此文章用到了第三方的package: photo_view,hero动画 可参考【Flutter实战第二版】的介绍(https://book.flutterchina.club/chapter9/hero.html#自实现hero动画)
主要涉及到两个文件:animation_net_image.dart和image_browser.dart
animation_net_image.dart这个文件是自定义可点击放大的图片;
image_browser.dart主要是显示放大图片的浏览器
1.直接上代码(animation_net_image.dart)
import 'package:flutter/widgets.dart';
import 'package:yp_erp/Common/Util/image_url_format.dart';
import 'package:yp_erp/Common/Util/image_url_util.dart';
import 'package:yp_erp/Common/View/image_browser.dart';
class AnimationImageBuild extends StatefulWidget {
final String heroTag;// 一定要保证和其他页面不一样
final String imageURL; // 原图片url
final BoxFit fit;
final double width;
final double height;
const AnimationImageBuild(
this.imageURL,
this.width,
this.height,
this.heroTag,
this.fit, {
Key key,
}) : super(key: key);
@override
_AnimationImageBuildState createState() => _AnimationImageBuildState();
}
class _AnimationImageBuildState extends State<AnimationImageBuild> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
showImageBrowser(
context,
0,
[ImageUrlUtil.formatUrl(widget.imageURL)],
heroTag: widget.heroTag + widget.imageURL,
);
},
child: Hero(
tag: widget.heroTag + widget.imageURL,
child: Image.network(
resizeImageUrlFill(
widget.imageURL, widget.height.round(), widget.width.round()),
height: widget.height,
width: widget.width,
fit: widget.fit,
),
),
);
}
}
resizeImageUrlFill和ImageUrlUtil.formatUr主要是我们自己对图片的处理,你自己传图片url即可
2.(image_browser.dart)文件
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
void showImageBrowser(
BuildContext context,
final int index,
List<String> imageURLs, {
bool verticalGallery = false,
Object heroTag = 0,
}) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GalleryPhotoViewWrapper(
imageURLs: imageURLs,
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
heroTag: heroTag,
initialIndex: index,
scrollDirection: verticalGallery ? Axis.vertical : Axis.horizontal,
),
),
);
}
class GalleryPhotoViewWrapper extends StatefulWidget {
final LoadingBuilder loadingBuilder;
final BoxDecoration backgroundDecoration;
final dynamic minScale;
final dynamic maxScale;
final int initialIndex;
final Object heroTag;
final PageController pageController;
final List<String> imageURLs;
final Axis scrollDirection;
GalleryPhotoViewWrapper({
Key key,
this.loadingBuilder,
this.backgroundDecoration,
this.minScale,
this.maxScale,
this.heroTag = 0,
this.initialIndex = 0,
@required this.imageURLs,
this.scrollDirection = Axis.horizontal,
}) : pageController = PageController(initialPage: initialIndex),
super(key: key);
@override
State<StatefulWidget> createState() {
return _GalleryPhotoViewWrapperState();
}
}
class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
int currentIndex = 0;
void onPageChanged(int index) {
setState(() {
currentIndex = index;
});
}
@override
Widget build(BuildContext context) {
if (currentIndex == 0) {
currentIndex = widget.initialIndex;
}
return Scaffold(
body: Container(
decoration: widget.backgroundDecoration,
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
),
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
PhotoViewGallery.builder(
scrollPhysics: const BouncingScrollPhysics(),
builder: _buildItem,
itemCount: widget.imageURLs.length,
loadingBuilder: widget.loadingBuilder,
backgroundDecoration: widget.backgroundDecoration,
pageController: widget.pageController,
onPageChanged: onPageChanged,
scrollDirection: widget.scrollDirection,
),
Container(
padding: const EdgeInsets.only(bottom: 20, left: 20, right: 20),
child: Text(
" ${currentIndex + 1} / ${widget.imageURLs.length}",
style: const TextStyle(
color: Colors.white,
fontSize: 17.0,
decoration: null,
),
),
)
],
),
),
),
);
}
PhotoViewGalleryPageOptions _buildItem(BuildContext context, int index) {
final String item = widget.imageURLs[index];
return PhotoViewGalleryPageOptions(
imageProvider: NetworkImage(item),
initialScale: PhotoViewComputedScale.contained,
minScale: PhotoViewComputedScale.contained * (0.5 + index / 10),
maxScale: PhotoViewComputedScale.covered * 4.1,
heroAttributes: PhotoViewHeroAttributes(tag: widget.heroTag),
);
}
}
用的时候举个:AnimationImageBuild(url, 88, 88, "appraisal" + state.model.code, BoxFit.fill);就可以了