##### demo 地址: https://github.com/iotjin/jh_flutter_demo
flutter好用的轮子推荐四-可定制的图片预览查看器photo_view
flutter九宫格图片查看器
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
const Color selColor =Colors.white;
const Color otherColor = Colors.grey;
class FadeRoute extends PageRouteBuilder {
final Widget page;
FadeRoute({this.page}): super(
pageBuilder: (
BuildContext context,
Animation animation,
Animation secondaryAnimation,
) =>page,transitionsBuilder: (
BuildContext context,
Animation animation,
Animation secondaryAnimation,
Widget child,
) =>FadeTransition(
opacity: animation,
child: child,
),
);
}
class JhPhotoAllScreenShow extends StatefulWidget {
List imgDataArr=[];
int index=0;
String heroTag;
PageController controller;
GestureTapCallback onLongPress;
JhPhotoAllScreenShow({
Key key,
@required this.imgDataArr,
this.index,
this.onLongPress,
this.controller,
this.heroTag
}) : super(key: key){
controller=PageController(initialPage: index);
}
@override
_JhPhotoAllScreenShowState createState() => _JhPhotoAllScreenShowState();
}
class _JhPhotoAllScreenShowState extends State {
int currentIndex=0;
@override
void initState() {
// TODO: implement initState
super.initState();
currentIndex=widget.index;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Positioned(
top: 0,
left: 0,
bottom: 0,
right: 0,
child:
GestureDetector(
child:
Container(
color: Colors.black,
child: PhotoViewGallery.builder(
scrollPhysics: const BouncingScrollPhysics(),
builder: (BuildContext context, int index) {
return PhotoViewGalleryPageOptions(
imageProvider: NetworkImage(widget.imgDataArr[index]),
heroAttributes: widget.heroTag !=null?PhotoViewHeroAttributes(tag: widget.heroTag):null,
);
},
itemCount: widget.imgDataArr.length,
loadingChild: Container(),
backgroundDecoration: null,
pageController: widget.controller,
enableRotation: true,
onPageChanged: (index){
setState(() {
currentIndex=index;
});
},
)
),
onTap: (){
Navigator.of(context).pop();
},
onLongPress: widget.onLongPress,
)
),
Positioned(
top: MediaQuery.of(context).padding.top+30,
width: MediaQuery.of(context).size.width,
child: Center(
child: Text("${currentIndex+1}/${widget.imgDataArr.length}",style: TextStyle(color: Colors.white,fontSize: 16)),
),
),
Positioned(
right: 10,
top: MediaQuery.of(context).padding.top+15,
child: IconButton(
icon: Icon(Icons.close,size: 30,color: Colors.white,),
onPressed: (){
Navigator.of(context).pop();
},
),
),
Align(
alignment: Alignment.bottomCenter,
child:
Container(
// color: Colors.red,
width: widget.imgDataArr.length>=6 ? 200:widget.imgDataArr.length<3 ? 50:100,
height: widget.imgDataArr.length==1 ? 0:50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(
widget.imgDataArr.length,
(i) => GestureDetector(
child: CircleAvatar(
// foregroundColor: Theme.of(context).primaryColor,
radius: 5.0,
backgroundColor: currentIndex == i ? selColor : otherColor,
),
),
).toList(),
),
)
)
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
const Color selColor =Colors.white;
const Color otherColor = Colors.grey;
// 底部显示小圆点
class NinePictureAllScreenShow extends PopupRoute {
final String barrierLabel;
final List picList;
final int index;
int startX;
int endX;
NinePictureAllScreenShow(this.picList, this.index, {this.barrierLabel});
@override
Duration get transitionDuration => Duration(milliseconds: 2000);
@override
Color get barrierColor => Colors.black; //背景颜色
@override
bool get barrierDismissible => true;
AnimationController _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController =
BottomSheet.createAnimationController(navigator.overlay);
return _animationController;
}
@override
Widget buildPage(BuildContext context, Animation animation,
Animation secondaryAnimation) {
return MediaQuery.removePadding(
removeTop: true,
context: context,
child: GestureDetector(
child: AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) => GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: _PictureWidget(picList, index),
),
),
),
);
}
}
class _PictureWidget extends StatefulWidget {
final List picList;
final int index;
_PictureWidget(this.picList, this.index);
@override
State createState() {
return _PictureWidgetState();
}
}
class _PictureWidgetState extends State<_PictureWidget> {
int startX = 0;
int endX = 0;
int index = 0;
@override
void initState() {
// TODO: implement initState
super.initState();
index = widget.index;
}
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.transparent,
child: new Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(0, 0, 0, 30),
child: Stack(
children: [
GestureDetector(
child: Center(
child: CachedNetworkImage(
imageUrl: widget.picList[index],
fit: BoxFit.fill,
),
),
onHorizontalDragDown: (detail) {
startX = detail.globalPosition.dx.toInt();
},
onHorizontalDragUpdate: (detail) {
endX = detail.globalPosition.dx.toInt();
},
onHorizontalDragEnd: (detail) {
_getIndex(endX - startX);
setState(() {});
},
onHorizontalDragCancel: () {},
),
Align(
alignment: Alignment.bottomCenter,
child:
Container(
// color: Colors.red,
width: widget.picList.length>=6 ? 200:widget.picList.length<3 ? 50:100,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(
widget.picList.length,
(i) => GestureDetector(
child: CircleAvatar(
// foregroundColor: Theme.of(context).primaryColor,
foregroundColor: selColor,
radius: 5.0,
backgroundColor: index == i ? selColor : otherColor,
),
onTap: () {
setState(() {
startX = endX = 0;
index = i;
});
},
),
).toList(),
),
)
)
],
),
alignment: Alignment.center,
),
);
}
void _getIndex(int delta) {
if (delta > 50) {
setState(() {
index--;
index = index.clamp(0, widget.picList.length - 1);
});
} else if (delta < 50) {
setState(() {
index++;
index = index.clamp(0, widget.picList.length - 1);
});
}
}
}