🍿
【Flutter】image_pickerで複数画像を一覧表示させる
プロジェクト作成
こちらのドキュメントに従って進めました。
image_picker
写真/動画の選択には「image_picker」ライブラリを利用しました。
できること(Examle)
final ImagePicker picker = ImagePicker();
// ギャラリーから画像を1つ選択
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
// カメラを起動して画像撮影
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
// ギャラリーから動画を1つ選択
final XFile? galleryVideo = await picker.pickVideo(source: ImageSource.gallery);
// カメラを起動して動画撮影
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
// ギャラリーから画像を複数選択
final List<XFile> images = await picker.pickMultiImage();
// ギャラリーから画像(もしくは動画)を1つ選択
final XFile? media = await picker.pickMedia();
// ギャラリーから画像や動画を複数選択
final List<XFile> medias = await picker.pickMultipleMedia();
画像選択から一覧表示まで(pickMultipleMedia)
初期画面
選択画面(未選択)
選択画面(選択中)
一覧表示
実装したコード
簡易的に実装してみました。(リファクタリングは特にしていません)
動画表示は「video_thumbnail」ライブラリを介してGridViewに表示しています。
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:mime/mime.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<XFile>? _mediaFileList;
dynamic _pickImageError;
String? _retrieveDataError;
final ImagePicker _picker = ImagePicker();
Future _getVideoThumbnail(String filePath) async {
return await VideoThumbnail.thumbnailFile(
video: filePath,
imageFormat: ImageFormat.JPEG,
maxWidth:
128, // specify the width of the thumbnail, let the height auto-scaled to keep the source aspect ratio
quality: 75,
);
}
// 画像をギャラリーから選ぶ関数
Future pickImage() async {
try {
final List<XFile> pickedFileList = await _picker.pickMultipleMedia();
setState(() {
_mediaFileList = pickedFileList;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
}
Widget _previewVideo() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
return const Text(
'You have not yet picked a video',
textAlign: TextAlign.center,
);
}
Widget _previewImages() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_mediaFileList != null) {
return GridView.count(
crossAxisCount: 3,
children: _mediaFileList!.map((XFile file) {
final String? mime = lookupMimeType(file.path);
debugPrint('Debug message: $mime');
return (mime == null || mime.startsWith('image/'))
? Image.file(
File(file.path),
fit: BoxFit.cover,
)
: FutureBuilder(
future: _getVideoThumbnail(file.path),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Image.file(
File(snapshot.data),
fit: BoxFit.cover,
);
}
return const Center(child: CircularProgressIndicator());
},
);
}).toList());
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: _previewImages()),
floatingActionButton: FloatingActionButton(
onPressed: pickImage,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
Text? _getRetrieveErrorWidget() {
if (_retrieveDataError != null) {
final Text result = Text(_retrieveDataError!);
_retrieveDataError = null;
return result;
}
return null;
}
}
これからやりたいこと
端末から選択した画像や動画を Firebase storage や AWS S3 にアップロードして、
一覧表示で画像を選択した際に端末にダウンロードできるアプリを作成したい。
Discussion