import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:photo_gallery/photo_gallery.dart'; import 'package:transparent_image/transparent_image.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State { List _collections; bool _loading = false; @override void initState() { super.initState(); _loading = true; initAsync(); } Future initAsync() async { if (await _promptPermissionSetting()) { List collections = await PhotoGallery.listAlbums(mediumType: MediumType.image); setState(() { _collections = collections; _loading = false; }); } setState(() { _loading = false; }); } Future _promptPermissionSetting() async { if (Platform.isIOS && await Permission.storage.request().isGranted && await Permission.photos.request().isGranted || Platform.isAndroid && await Permission.storage.request().isGranted) { return true; } return false; } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Photo gallery example'), ), body: _loading ? Center( child: CircularProgressIndicator(), ) : LayoutBuilder( builder: (context, constraints) { double gridWidth = (constraints.maxWidth - 20) / 3; double gridHeight = gridWidth + 33; double ratio = gridWidth / gridHeight; return Container( padding: EdgeInsets.all(5), child: GridView.count( childAspectRatio: ratio, crossAxisCount: 3, mainAxisSpacing: 5.0, crossAxisSpacing: 5.0, children: [ ...?_collections?.map( (collection) => GestureDetector( onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (context) => CollectionPage(collection))), child: Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(5.0), child: Container( color: Colors.grey[300], height: gridWidth, width: gridWidth, child: FadeInImage( fit: BoxFit.cover, placeholder: MemoryImage(kTransparentImage), image: AlbumThumbnailProvider( albumId: collection.id, highQuality: true, ), ), ), ), Container( alignment: Alignment.topLeft, padding: EdgeInsets.only(left: 2.0), child: Text( collection.name, maxLines: 1, textAlign: TextAlign.start, style: TextStyle( height: 1.2, fontSize: 16, ), ), ), Container( alignment: Alignment.topLeft, padding: EdgeInsets.only(left: 2.0), child: Text( collection.count.toString(), textAlign: TextAlign.start, style: TextStyle( height: 1.2, fontSize: 12, ), ), ), ], ), ), ), ], ), ); }, ), ), ); } } class CollectionPage extends StatefulWidget { final Album collection; CollectionPage(Album collection) : collection = collection; @override State createState() => CollectionPageState(); } class CollectionPageState extends State { List _media; @override void initState() { super.initState(); initAsync(); } void initAsync() async { MediaPage mediaPage = await widget.collection.listMedia(); setState(() { _media = mediaPage.items; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( leading: IconButton( icon: Icon(Icons.arrow_back_ios), onPressed: () => Navigator.of(context).pop(), ), title: Text(widget.collection.name), ), body: GridView.count( crossAxisCount: 3, mainAxisSpacing: 1.0, crossAxisSpacing: 1.0, children: [ ...?_media?.map( (media) => GestureDetector( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (context) => ViewerPage(media))), child: Container( color: Colors.grey[300], child: FadeInImage( fit: BoxFit.cover, placeholder: MemoryImage(kTransparentImage), image: ThumbnailProvider( mediumId: media.id, highQuality: true, ), ), ), ), ), ], ), ), ); } } class ViewerPage extends StatelessWidget { final Medium media; ViewerPage(Medium media) : media = media; @override Widget build(BuildContext context) { DateTime date = media.creationDate ?? media.modifiedDate; return MaterialApp( home: Scaffold( appBar: AppBar( leading: IconButton( onPressed: () => Navigator.of(context).pop(), icon: Icon(Icons.arrow_back_ios), ), title: Text(date?.toLocal().toString()), ), body: Container( alignment: Alignment.center, child: FadeInImage( fit: BoxFit.cover, placeholder: MemoryImage(kTransparentImage), image: PhotoProvider(mediumId: media.id), ), ), ), ); } }