Skip to content

Commit

Permalink
update package
Browse files Browse the repository at this point in the history
  • Loading branch information
Beshoy Melika committed Jun 4, 2023
1 parent 080d664 commit d337a69
Show file tree
Hide file tree
Showing 8 changed files with 476 additions and 228 deletions.
40 changes: 40 additions & 0 deletions lib/app_cached_network_image.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

class AppCachedNetworkImage extends StatelessWidget {
final Widget? loadingWidget;
final Widget? errorWidget;
final double? height;
final double? width;
final BoxFit? fit;
final double radius;
final String imageUrl;

const AppCachedNetworkImage({
super.key,
required this.imageUrl,
required this.radius,
this.loadingWidget,
this.errorWidget,
this.fit,
this.height,
this.width,
});

@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(radius)),
child: CachedNetworkImage(
height: height,
width: width,
fit: fit,
imageUrl: imageUrl,
placeholder: (context, url) =>
loadingWidget ?? const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
errorWidget ?? const Icon(Icons.error),
),
);
}
}
177 changes: 133 additions & 44 deletions lib/gallery_image_view_wrapper.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:galleryimage/app_cached_network_image.dart';

import 'gallery_item_model.dart';

// to view image in full screen
class GalleryImageViewWrapper extends StatefulWidget {
final LoadingBuilder? loadingBuilder;
final BoxDecoration? backgroundDecoration;
final Color? backgroundColor;
final int? initialIndex;
final PageController pageController;
final List<GalleryItemModel> galleryItems;
final Axis scrollDirection;
final String? titleGallery;
final Widget? loadingWidget;
final Widget? errorWidget;
final double minScale;
final double maxScale;
final double radius;
final bool reverse;
final bool showListInGalley;
final bool showAppBar;
final bool closeWhenSwipeUp;
final bool closeWhenSwipeDown;

GalleryImageViewWrapper({
const GalleryImageViewWrapper({
Key? key,
this.loadingBuilder,
this.titleGallery,
this.backgroundDecoration,
this.initialIndex,
required this.titleGallery,
required this.backgroundColor,
required this.initialIndex,
required this.galleryItems,
this.scrollDirection = Axis.horizontal,
}) : pageController = PageController(initialPage: initialIndex ?? 0),
super(key: key);
required this.loadingWidget,
required this.errorWidget,
required this.minScale,
required this.maxScale,
required this.radius,
required this.reverse,
required this.showListInGalley,
required this.showAppBar,
required this.closeWhenSwipeUp,
required this.closeWhenSwipeDown,
}) : super(key: key);

@override
State<StatefulWidget> createState() {
Expand All @@ -33,46 +45,123 @@ class GalleryImageViewWrapper extends StatefulWidget {
}

class _GalleryImageViewWrapperState extends State<GalleryImageViewWrapper> {
final minScale = PhotoViewComputedScale.contained * 0.8;
final maxScale = PhotoViewComputedScale.covered * 8;
late final PageController _controller =
PageController(initialPage: widget.initialIndex ?? 0);
int _currentPage = 0;

@override
void initState() {
_currentPage = 0;
_controller.addListener(() {
setState(() {
_currentPage = _controller.page?.toInt() ?? 0;
});
});
super.initState();
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.titleGallery ?? "Gallery"),
),
body: Container(
decoration: widget.backgroundDecoration,
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
appBar: widget.showAppBar
? AppBar(
title: Text(widget.titleGallery ?? "Gallery"),
)
: null,
backgroundColor: widget.backgroundColor,
body: SafeArea(
child: Container(
constraints:
BoxConstraints.expand(height: MediaQuery.of(context).size.height),
child: Column(
children: [
Expanded(
child: GestureDetector(
onVerticalDragEnd: (details) {
if (widget.closeWhenSwipeUp &&
details.primaryVelocity! < 0) {
//'up'
Navigator.of(context).pop();
}
if (widget.closeWhenSwipeDown &&
details.primaryVelocity! > 0) {
// 'down'
Navigator.of(context).pop();
}
},
child: PageView.builder(
reverse: widget.reverse,
controller: _controller,
itemCount: widget.galleryItems.length,
itemBuilder: (context, index) =>
_buildImage(widget.galleryItems[index]),
),
),
),
if (widget.showListInGalley)
SizedBox(
height: 80,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: widget.galleryItems
.map((e) => _buildLitImage(e))
.toList(),
),
),
),
],
),
),
child: PhotoViewGallery.builder(
scrollPhysics: const BouncingScrollPhysics(),
builder: _buildImage,
itemCount: widget.galleryItems.length,
loadingBuilder: widget.loadingBuilder,
backgroundDecoration: widget.backgroundDecoration,
pageController: widget.pageController,
scrollDirection: widget.scrollDirection,
),
);
}

// build image with zooming
Widget _buildImage(GalleryItemModel item) {
return Hero(
tag: item.id,
child: InteractiveViewer(
minScale: widget.minScale,
maxScale: widget.maxScale,
child: Center(
child: AppCachedNetworkImage(
imageUrl: item.imageUrl,
loadingWidget: widget.loadingWidget,
errorWidget: widget.errorWidget,
radius: widget.radius,
),
),
),
);
}

// build image with zooming
PhotoViewGalleryPageOptions _buildImage(BuildContext context, int index) {
final GalleryItemModel item = widget.galleryItems[index];
return PhotoViewGalleryPageOptions.customChild(
child: CachedNetworkImage(
imageUrl: item.imageUrl,
placeholder: (context, url) =>
const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
Widget _buildLitImage(GalleryItemModel item) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: GestureDetector(
onTap: () {
setState(() {
_controller.jumpToPage(item.index);
});
},
child: AppCachedNetworkImage(
height: _currentPage == item.index ? 70 : 60,
width: _currentPage == item.index ? 70 : 60,
fit: BoxFit.cover,
imageUrl: item.imageUrl,
errorWidget: widget.errorWidget,
radius: widget.radius,
loadingWidget: widget.loadingWidget,
),
),
initialScale: PhotoViewComputedScale.contained,
minScale: minScale,
maxScale: maxScale,
heroAttributes: PhotoViewHeroAttributes(tag: item.id),
);
}
}
10 changes: 8 additions & 2 deletions lib/gallery_item_model.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
class GalleryItemModel {
GalleryItemModel({required this.id, required this.imageUrl});
// id image (image url) to use in hero animation
GalleryItemModel({
required this.id,
required this.imageUrl,
required this.index,
});
// index in list of image
final int index;
// id image (image url) to use in hero animation
final String id;
// image url
final String imageUrl;
Expand Down
27 changes: 17 additions & 10 deletions lib/gallery_item_thumbnail.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:galleryimage/app_cached_network_image.dart';

import 'gallery_item_model.dart';

// to show image in Row
class GalleryItemThumbnail extends StatelessWidget {
const GalleryItemThumbnail({Key? key, required this.galleryItem, this.onTap})
: super(key: key);

final GalleryItemModel galleryItem;

final GestureTapCallback? onTap;
final Widget? loadingWidget;
final Widget? errorWidget;
final double radius;

const GalleryItemThumbnail(
{Key? key,
required this.galleryItem,
required this.onTap,
required this.radius,
required this.loadingWidget,
required this.errorWidget})
: super(key: key);

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Hero(
tag: galleryItem.id,
child: CachedNetworkImage(
child: AppCachedNetworkImage(
fit: BoxFit.cover,
imageUrl: galleryItem.imageUrl,
height: 100.0,
placeholder: (context, url) =>
const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
loadingWidget: loadingWidget,
errorWidget: errorWidget,
radius: radius,
),
),
);
Expand Down
Loading

0 comments on commit d337a69

Please sign in to comment.