fixed hero tags to animate only between a collection lens and an item from that lens

This commit is contained in:
Thibault Deckers 2020-03-09 19:22:06 +09:00
parent 13dcba9015
commit ad653e8730
4 changed files with 35 additions and 27 deletions

View file

@ -64,6 +64,8 @@ class CollectionLens with ChangeNotifier {
List<ImageEntry> get sortedEntries => List.unmodifiable(sections.entries.expand((e) => e.value)); List<ImageEntry> get sortedEntries => List.unmodifiable(sections.entries.expand((e) => e.value));
Object heroTag(ImageEntry entry) => '$hashCode${entry.uri}';
void sort(SortFactor sortFactor) { void sort(SortFactor sortFactor) {
this.sortFactor = sortFactor; this.sortFactor = sortFactor;
updateSections(); updateSections();

View file

@ -44,6 +44,7 @@ class SectionSliver extends StatelessWidget {
child: Thumbnail( child: Thumbnail(
entry: entry, entry: entry,
extent: mqWidth / columnCount, extent: mqWidth / columnCount,
heroTag: collection.heroTag(entry),
), ),
); );
}, },

View file

@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
class Thumbnail extends StatelessWidget { class Thumbnail extends StatelessWidget {
final ImageEntry entry; final ImageEntry entry;
final double extent; final double extent;
final Object heroTag;
static final Color borderColor = Colors.grey.shade700; static final Color borderColor = Colors.grey.shade700;
static const double borderWidth = .5; static const double borderWidth = .5;
@ -16,6 +17,7 @@ class Thumbnail extends StatelessWidget {
Key key, Key key,
@required this.entry, @required this.entry,
@required this.extent, @required this.extent,
this.heroTag,
}) : super(key: key); }) : super(key: key);
@override @override
@ -26,33 +28,36 @@ class Thumbnail extends StatelessWidget {
width: 50, width: 50,
height: 50, height: 50,
builder: (bytes) { builder: (bytes) {
return Hero( final image = Image.memory(
tag: entry.uri, bytes,
flightShuttleBuilder: ( width: extent,
BuildContext flightContext, height: extent,
Animation<double> animation, fit: BoxFit.cover,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
// use LayoutBuilder only during hero animation
return LayoutBuilder(builder: (context, constraints) {
final dim = min(constraints.maxWidth, constraints.maxHeight);
return Image.memory(
bytes,
width: dim,
height: dim,
fit: BoxFit.cover,
);
});
},
child: Image.memory(
bytes,
width: extent,
height: extent,
fit: BoxFit.cover,
),
); );
return heroTag == null
? image
: Hero(
tag: heroTag,
flightShuttleBuilder: (
BuildContext flightContext,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
// use LayoutBuilder only during hero animation
return LayoutBuilder(builder: (context, constraints) {
final dim = min(constraints.maxWidth, constraints.maxHeight);
return Image.memory(
bytes,
width: dim,
height: dim,
fit: BoxFit.cover,
);
});
},
child: image,
);
}, },
); );
return Container( return Container(

View file

@ -80,7 +80,7 @@ class ImagePageState extends State<ImagePage> with AutomaticKeepAliveClientMixin
), ),
backgroundDecoration: backgroundDecoration, backgroundDecoration: backgroundDecoration,
heroAttributes: PhotoViewHeroAttributes( heroAttributes: PhotoViewHeroAttributes(
tag: entry.uri, tag: widget.collection.heroTag(entry),
transitionOnUserGestures: true, transitionOnUserGestures: true,
), ),
scaleStateChangedCallback: scaleStateChangedCallback, scaleStateChangedCallback: scaleStateChangedCallback,