feat(ui): Implement a Hero transition
This commit is contained in:
		
							parent
							
								
									bea3ff8b78
								
							
						
					
					
						commit
						e12b9a0c72
					
				| @ -159,23 +159,24 @@ class AnimeListPage extends StatelessWidget { | |||||||
|                         ); |                         ); | ||||||
|                       }, |                       }, | ||||||
|                       child: AnimeCoverImage( |                       child: AnimeCoverImage( | ||||||
|                         url: anime.thumbnailUrl, |                           url: anime.thumbnailUrl, | ||||||
|                         onTap: () { |                           hero: anime.id, | ||||||
|                           context.read<DetailsBloc>().add( |                           onTap: () { | ||||||
|                             AnimeDetailsRequestedEvent(anime), |                             context.read<DetailsBloc>().add( | ||||||
|                           ); |                               AnimeDetailsRequestedEvent(anime), | ||||||
|                         }, |                             ); | ||||||
|                         extra: Align( |                           }, | ||||||
|                           alignment: Alignment.centerRight, |                           extra: Align( | ||||||
|                           child: Padding( |                             alignment: Alignment.centerRight, | ||||||
|                             padding: const EdgeInsets.only(right: 8), |                             child: Padding( | ||||||
|                             child: Text( |                               padding: const EdgeInsets.only(right: 8), | ||||||
|                               '${anime.episodesWatched}/${anime.episodesTotal ?? "???"}', |                               child: Text( | ||||||
|                               style: Theme.of(context).textTheme.titleMedium, |                                 '${anime.episodesWatched}/${anime.episodesTotal ?? "???"}', | ||||||
|  |                                 style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |                               ), | ||||||
|                             ), |                             ), | ||||||
|                           ), |                           ), | ||||||
|                         ), |                         ), | ||||||
|                       ), |  | ||||||
|                     ); |                     ); | ||||||
|                   }, |                   }, | ||||||
|                 ), |                 ), | ||||||
| @ -208,23 +209,24 @@ class AnimeListPage extends StatelessWidget { | |||||||
|                         ); |                         ); | ||||||
|                       }, |                       }, | ||||||
|                       child: AnimeCoverImage( |                       child: AnimeCoverImage( | ||||||
|                         url: manga.thumbnailUrl, |                         hero: manga.id, | ||||||
|                         onTap: () { |                           url: manga.thumbnailUrl, | ||||||
|                           context.read<DetailsBloc>().add( |                           onTap: () { | ||||||
|                             MangaDetailsRequestedEvent(manga), |                             context.read<DetailsBloc>().add( | ||||||
|                           ); |                               MangaDetailsRequestedEvent(manga), | ||||||
|                         }, |                             ); | ||||||
|                         extra: Align( |                           }, | ||||||
|                           alignment: Alignment.centerRight, |                           extra: Align( | ||||||
|                           child: Padding( |                             alignment: Alignment.centerRight, | ||||||
|                             padding: const EdgeInsets.only(right: 8), |                             child: Padding( | ||||||
|                             child: Text( |                               padding: const EdgeInsets.only(right: 8), | ||||||
|                               '${manga.chaptersRead}/${manga.chaptersTotal ?? "???"}', |                               child: Text( | ||||||
|                               style: Theme.of(context).textTheme.titleMedium, |                                 '${manga.chaptersRead}/${manga.chaptersTotal ?? "???"}', | ||||||
|  |                                 style: Theme.of(context).textTheme.titleMedium, | ||||||
|  |                               ), | ||||||
|                             ), |                             ), | ||||||
|                           ), |                           ), | ||||||
|                         ), |                         ), | ||||||
|                       ), |  | ||||||
|                     ); |                     ); | ||||||
|                   }, |                   }, | ||||||
|                 ), |                 ), | ||||||
|  | |||||||
| @ -38,9 +38,9 @@ class DetailsPage extends StatelessWidget { | |||||||
|               children: [ |               children: [ | ||||||
|                 Row( |                 Row( | ||||||
|                   crossAxisAlignment: CrossAxisAlignment.start, |                   crossAxisAlignment: CrossAxisAlignment.start, | ||||||
|                   children: [ |                   children: [AnimeCoverImage( | ||||||
|                     AnimeCoverImage( |                         url: state.data!.thumbnailUrl, | ||||||
|                       url: state.data!.thumbnailUrl, |                         hero: state.data!.id, | ||||||
|                     ), |                     ), | ||||||
| 
 | 
 | ||||||
|                     Expanded( |                     Expanded( | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import 'package:flutter/material.dart'; | |||||||
| class AnimeCoverImage extends StatelessWidget { | class AnimeCoverImage extends StatelessWidget { | ||||||
|   const AnimeCoverImage({ |   const AnimeCoverImage({ | ||||||
|     required this.url, |     required this.url, | ||||||
|  |     required this.hero, | ||||||
|     this.cached = true, |     this.cached = true, | ||||||
|     this.extra, |     this.extra, | ||||||
|     this.onTap, |     this.onTap, | ||||||
| @ -16,6 +17,9 @@ class AnimeCoverImage extends StatelessWidget { | |||||||
|   /// Flag indicating if the image should be cached. |   /// Flag indicating if the image should be cached. | ||||||
|   final bool cached; |   final bool cached; | ||||||
| 
 | 
 | ||||||
|  |   /// The hero tag of the image. | ||||||
|  |   final String hero; | ||||||
|  |    | ||||||
|   /// An extra widget with a translucent backdrop. |   /// An extra widget with a translucent backdrop. | ||||||
|   final Widget? extra; |   final Widget? extra; | ||||||
| 
 | 
 | ||||||
| @ -24,46 +28,51 @@ class AnimeCoverImage extends StatelessWidget { | |||||||
|    |    | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return ClipRRect( |     return Hero( | ||||||
|       borderRadius: BorderRadius.circular(8), |       tag: hero, | ||||||
|       child: SizedBox( |       child: ClipRRect( | ||||||
|         height: 100 * (16 / 9), |         borderRadius: BorderRadius.circular(8), | ||||||
|         width: 120, |         child: Material( | ||||||
|         child: InkWell( |           child: SizedBox( | ||||||
|           onTap: onTap ?? () {}, |             height: 100 * (16 / 9), | ||||||
|           child: Stack( |             width: 120, | ||||||
|             children: [ |             child: InkWell( | ||||||
|               Positioned( |               onTap: onTap ?? () {}, | ||||||
|                 left: 0, |               child: Stack( | ||||||
|                 right: 0, |                 children: [ | ||||||
|                 top: 0, |                   Positioned( | ||||||
|                 bottom: 0, |                     left: 0, | ||||||
|                 child: DecoratedBox( |                     right: 0, | ||||||
|                   decoration: BoxDecoration( |                     top: 0, | ||||||
|                     image: DecorationImage( |                     bottom: 0, | ||||||
|                       image: cached ? |                     child: DecoratedBox( | ||||||
|                       CachedNetworkImageProvider(url) as ImageProvider : |                       decoration: BoxDecoration( | ||||||
|                       NetworkImage(url), |                         image: DecorationImage( | ||||||
|                       fit: BoxFit.cover, |                           image: cached ? | ||||||
|  |                             CachedNetworkImageProvider(url) as ImageProvider : | ||||||
|  |                             NetworkImage(url), | ||||||
|  |                           fit: BoxFit.cover, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
|                 ), |  | ||||||
|               ), |  | ||||||
| 
 | 
 | ||||||
|               if (extra != null) |                   if (extra != null) | ||||||
|                 Positioned( |                     Positioned( | ||||||
|                   left: 0, |                       left: 0, | ||||||
|                   bottom: 0, |                       bottom: 0, | ||||||
|                   right: 0, |                       right: 0, | ||||||
|                   child: SizedBox( |                       child: SizedBox( | ||||||
|                     height: 40, |                         height: 40, | ||||||
|                     child: ColoredBox( |                         child: ColoredBox( | ||||||
|                       color: Colors.black54, |                           color: Colors.black54, | ||||||
|                       child: extra, |                           child: extra, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|                     ), |                     ), | ||||||
|                   ), |                 ], | ||||||
|                 ), |               ), | ||||||
|             ], |             ), | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|  | |||||||
| @ -76,6 +76,8 @@ class ListItem extends StatelessWidget { | |||||||
|           children: [ |           children: [ | ||||||
|             AnimeCoverImage( |             AnimeCoverImage( | ||||||
|               cached: cached, |               cached: cached, | ||||||
|  |               // TODO(Unknown): Have the ID here | ||||||
|  |               hero: thumbnailUrl, | ||||||
|               extra: imageExtra, |               extra: imageExtra, | ||||||
|               url: thumbnailUrl, |               url: thumbnailUrl, | ||||||
|             ), |             ), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user