Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added HeroPhotoView class which is more suitable for using with Hero … #19

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,41 @@ dynamic ([double](https://docs.flutter.io/flutter/dart-core/double-class.html) o
bool gaplessPlayback
})

## HeroPhotoView class

A specific [PhotoView](/lib/photo_view.dart) used in playing [Hero](https://docs.flutter.io/flutter/widgets/Hero-class.html) animation.

#### Sample code

```dart
new HeroPhotoView(
imageProvider: imageProvider,
backgroundColor: Colors.white,
minScale: PhotoViewScaleBoundary.contained,
maxScale: 2.0,
gaplessPlayback: false,
size: MediaQuery.of(context).size
);
```

### Constructor

[HeroPhotoView](/lib/hero_photo_view.dart)({
@required [ImageProvider](https://docs.flutter.io/flutter/painting/ImageProvider-class.html) imageProvider,
[Color](https://docs.flutter.io/flutter/dart-ui/Color-class.html) backgroundColor,
dynamic ([double](https://docs.flutter.io/flutter/dart-core/double-class.html) or [PhotoViewScaleBoundary](/lib/photo_view_scale_boundary.dart)) minScale,
dynamic ([double](https://docs.flutter.io/flutter/dart-core/double-class.html) or [PhotoViewScaleBoundary](/lib/photo_view_scale_boundary.dart)) maxScale,
bool gaplessPlayback,
[Size](https://docs.flutter.io/flutter/dart-ui/Size-class.html) size})

Instead of using [FutureBuilder](https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html) in the normal [PhotoView](/lib/photo_view.dart), [HeroPhotoView](/lib/hero_photo_view.dart) uses [setState()](https://docs.flutter.io/flutter/widgets/State/setState.html) method to update UI after [ImageProvider](https://docs.flutter.io/flutter/painting/ImageProvider-class.html) being resolved.

The zoom scale can be clamped by `minScale` and `maxScale` params.

`backgroundColor`, changes the background behind image, defaults to `Colors.black`.

The parameter `gaplessPlayback` is used to continue showing the old image (`true`), or briefly show nothing (`false`), when the `imageProvider` changes. By default it's set to `false`.

`size` defines the size of the scaling base of the image inside `PhotoView`, by default it is `MediaQuery.of(context).size`. This param is used by `PhotoViewInline` class.

**All but `imageProvider` are optional**
97 changes: 97 additions & 0 deletions lib/hero_photo_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_image_wrapper.dart';
import 'package:photo_view/photo_view_scale_boundaries.dart';
import 'package:photo_view/photo_view_scale_state.dart';
import 'package:photo_view/photo_view_utils.dart';

export 'package:photo_view/photo_view_scale_boundary.dart';

class HeroPhotoView extends PhotoView {
HeroPhotoView({
Key key,
@required ImageProvider imageProvider,
Color backgroundColor = const Color.fromRGBO(0, 0, 0, 1.0),
minScale,
maxScale,
bool gaplessPlayback = false,
Size size,
}) : super(
key: key,
imageProvider: imageProvider,
backgroundColor: backgroundColor,
minScale: minScale,
maxScale: maxScale,
gaplessPlayback: gaplessPlayback,
size: size);

@override
State<StatefulWidget> createState() {
return new _HeroPhotoViewState();
}
}

class _HeroPhotoViewState extends State<HeroPhotoView> {
PhotoViewScaleState _scaleState;
GlobalKey containerKey = new GlobalKey();
ImageInfo _imageInfo;

Future<ImageInfo> _getImage() {
Completer completer = new Completer<ImageInfo>();
ImageStream stream = widget.imageProvider.resolve(new ImageConfiguration());
var listener = (ImageInfo info, bool completed) {
completer.complete(info);
setState(() {
_imageInfo = info;
});
};
stream.addListener(listener);
completer.future.then((_) {
stream.removeListener(listener);
});
return completer.future;
}

void onDoubleTap() {
setState(() {
_scaleState = nextScaleState(_scaleState);
});
}

void onStartPanning() {
setState(() {
_scaleState = PhotoViewScaleState.zooming;
});
}

@override
void initState() {
_getImage();
super.initState();
_scaleState = PhotoViewScaleState.contained;
}

@override
Widget build(BuildContext context) {
if (_imageInfo == null) {
return new SizedBox();
}
return new PhotoViewImageWrapper(
onDoubleTap: onDoubleTap,
onStartPanning: onStartPanning,
imageProvider: widget.imageProvider,
imageInfo: _imageInfo,
scaleState: _scaleState,
backgroundColor: widget.backgroundColor,
gaplessPlayback: widget.gaplessPlayback,
size: widget.size ?? MediaQuery.of(context).size,
scaleBoundaries: new ScaleBoundaries(
widget.minScale ?? 0.0,
widget.maxScale ?? 100000000000.0,
imageInfo: _imageInfo,
size: widget.size ?? MediaQuery.of(context).size,
),
);
}
}