236 lines
7.4 KiB
Dart
236 lines
7.4 KiB
Dart
|
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<MyApp> {
|
||
|
List _collections;
|
||
|
bool _loading = false;
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
super.initState();
|
||
|
_loading = true;
|
||
|
initAsync();
|
||
|
}
|
||
|
|
||
|
Future<void> initAsync() async {
|
||
|
if (await _promptPermissionSetting()) {
|
||
|
List<Album> collections =
|
||
|
await PhotoGallery.listAlbums(mediumType: MediumType.image);
|
||
|
setState(() {
|
||
|
_collections = collections;
|
||
|
_loading = false;
|
||
|
});
|
||
|
}
|
||
|
setState(() {
|
||
|
_loading = false;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Future<bool> _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: <Widget>[
|
||
|
...?_collections?.map(
|
||
|
(collection) => GestureDetector(
|
||
|
onTap: () => Navigator.of(context).push(
|
||
|
MaterialPageRoute(
|
||
|
builder: (context) =>
|
||
|
CollectionPage(collection))),
|
||
|
child: Column(
|
||
|
children: <Widget>[
|
||
|
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<StatefulWidget> createState() => CollectionPageState();
|
||
|
}
|
||
|
|
||
|
class CollectionPageState extends State<CollectionPage> {
|
||
|
List<Medium> _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: <Widget>[
|
||
|
...?_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),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|