Cache photos to the left and right
This commit is contained in:
parent
a659fefa6d
commit
59dcc38ba5
6 changed files with 135 additions and 26 deletions
7
lib/events/photo_opened_event.dart
Normal file
7
lib/events/photo_opened_event.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
import 'package:photos/models/photo.dart';
|
||||
|
||||
class PhotoOpenedEvent {
|
||||
final Photo photo;
|
||||
|
||||
PhotoOpenedEvent(this.photo);
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:like_button/like_button.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/photo_opened_event.dart';
|
||||
import 'package:photos/favorite_photos_repository.dart';
|
||||
import 'package:photos/models/photo.dart';
|
||||
import 'package:photos/ui/extents_page_view.dart';
|
||||
import 'package:photos/ui/zoomable_image.dart';
|
||||
import 'package:photos/utils/share_util.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
@ -52,29 +55,35 @@ class _DetailPageState extends State<DetailPage> {
|
|||
|
||||
Widget _buildPageView() {
|
||||
_pageController = PageController(initialPage: _selectedIndex);
|
||||
return PageView.builder(
|
||||
return ExtentsPageView.extents(
|
||||
itemBuilder: (context, index) {
|
||||
final photo = _photos[index];
|
||||
final image = ZoomableImage(
|
||||
photo,
|
||||
shouldDisableScroll: (value) {
|
||||
setState(() {
|
||||
_shouldDisableScroll = value;
|
||||
});
|
||||
},
|
||||
final image = Hero(
|
||||
tag: photo.hashCode,
|
||||
child: ZoomableImage(
|
||||
photo,
|
||||
shouldDisableScroll: (value) {
|
||||
setState(() {
|
||||
_shouldDisableScroll = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
if (index == _selectedIndex) {
|
||||
Bus.instance.fire(PhotoOpenedEvent(photo));
|
||||
}
|
||||
return image;
|
||||
},
|
||||
onPageChanged: (int index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
_selectedIndex = index;
|
||||
Bus.instance.fire(PhotoOpenedEvent(widget.photos[index]));
|
||||
},
|
||||
physics: _shouldDisableScroll
|
||||
? NeverScrollableScrollPhysics()
|
||||
: PageScrollPhysics(),
|
||||
controller: _pageController,
|
||||
itemCount: _photos.length,
|
||||
extents: 1,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/photo_opened_event.dart';
|
||||
import 'package:photos/models/photo.dart';
|
||||
import 'package:photos/photo_sync_manager.dart';
|
||||
import 'package:photos/ui/detail_page.dart';
|
||||
|
@ -32,6 +35,24 @@ class _GalleryState extends State<Gallery> {
|
|||
List<Photo> _photos;
|
||||
RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
StreamSubscription<PhotoOpenedEvent> _subscription;
|
||||
Photo _openedPhoto;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_subscription = Bus.instance.on<PhotoOpenedEvent>().listen((event) {
|
||||
setState(() {
|
||||
_openedPhoto = event.photo;
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -127,10 +148,9 @@ class _GalleryState extends State<Gallery> {
|
|||
? Border.all(width: 4.0, color: Colors.blue)
|
||||
: null,
|
||||
),
|
||||
child: Hero(
|
||||
tag: photo.hashCode,
|
||||
child: ThumbnailWidget(photo),
|
||||
),
|
||||
child: photo == _openedPhoto
|
||||
? Hero(tag: photo.hashCode, child: ThumbnailWidget(photo))
|
||||
: ThumbnailWidget(photo),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:extended_image/extended_image.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:photos/core/cache/image_cache.dart';
|
||||
|
@ -21,7 +22,8 @@ class ZoomableImage extends StatefulWidget {
|
|||
_ZoomableImageState createState() => _ZoomableImageState();
|
||||
}
|
||||
|
||||
class _ZoomableImageState extends State<ZoomableImage> {
|
||||
class _ZoomableImageState extends State<ZoomableImage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
ImageProvider _imageProvider;
|
||||
bool _loadedSmallThumbnail = false;
|
||||
bool _loadingLargeThumbnail = false;
|
||||
|
@ -29,6 +31,10 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
bool _loadingFinalImage = false;
|
||||
bool _loadedFinalImage = false;
|
||||
ValueChanged<PhotoViewScaleState> _scaleStateChangedCallback;
|
||||
// AnimationController _animationController;
|
||||
// Animation _animation;
|
||||
// VoidCallback _animationListener;
|
||||
final doubleTapScales = [1.0, 2.0];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -37,6 +43,10 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
widget.shouldDisableScroll(value != PhotoViewScaleState.initial);
|
||||
}
|
||||
};
|
||||
// _animationController = AnimationController(
|
||||
// vsync: this,
|
||||
// duration: const Duration(milliseconds: 100),
|
||||
// );
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -49,12 +59,46 @@ class _ZoomableImageState extends State<ZoomableImage> {
|
|||
}
|
||||
|
||||
if (_imageProvider != null) {
|
||||
// return ExtendedImage(
|
||||
// image: _imageProvider,
|
||||
// gaplessPlayback: true,
|
||||
// mode: ExtendedImageMode.gesture,
|
||||
// enableSlideOutPage: true,
|
||||
// initGestureConfigHandler: (state) {
|
||||
// return GestureConfig(
|
||||
// inPageView: true,
|
||||
// initialScale: 1.0,
|
||||
// minScale: 1.0,
|
||||
// );
|
||||
// },
|
||||
// onDoubleTap: (ExtendedImageGestureState state) {
|
||||
// var pointerDownPosition = state.pointerDownPosition;
|
||||
// double begin = state.gestureDetails.totalScale;
|
||||
// double end;
|
||||
// _animation?.removeListener(_animationListener);
|
||||
// _animationController.stop();
|
||||
// _animationController.reset();
|
||||
// if (begin == doubleTapScales[0]) {
|
||||
// end = doubleTapScales[1];
|
||||
// } else {
|
||||
// end = doubleTapScales[0];
|
||||
// }
|
||||
// _animationListener = () {
|
||||
// state.handleDoubleTap(
|
||||
// scale: _animation.value,
|
||||
// doubleTapPosition: pointerDownPosition);
|
||||
// };
|
||||
// _animation =
|
||||
// _animationController.drive(Tween<double>(begin: begin, end: end));
|
||||
// _animation.addListener(_animationListener);
|
||||
// _animationController.forward();
|
||||
// },
|
||||
// );
|
||||
return PhotoView(
|
||||
imageProvider: _imageProvider,
|
||||
scaleStateChangedCallback: _scaleStateChangedCallback,
|
||||
minScale: PhotoViewComputedScale.contained,
|
||||
gaplessPlayback: true,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: widget.photo.hashCode),
|
||||
);
|
||||
} else {
|
||||
return loadWidget;
|
||||
|
|
46
pubspec.lock
46
pubspec.lock
|
@ -36,6 +36,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -120,6 +127,27 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
extended_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: extended_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.0"
|
||||
extended_image_library:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: extended_image_library
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -191,6 +219,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.1"
|
||||
http_client_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_client_helper
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -267,7 +302,7 @@ packages:
|
|||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.4"
|
||||
version: "1.7.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -345,13 +380,6 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.8"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
sensors:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -475,7 +503,7 @@ packages:
|
|||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.15"
|
||||
version: "0.2.16"
|
||||
toast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -50,6 +50,7 @@ dependencies:
|
|||
flutter_typeahead: ^1.8.1
|
||||
pull_to_refresh: ^1.5.7
|
||||
fluttertoast: ^4.0.1
|
||||
extended_image: ^0.9.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in a new issue