Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[image_picker] add getMedia method #3892

Merged
merged 5 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/image_picker/image_picker/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.8

* Adds `getMedia` and `getMultipleMedia` methods.

## 0.8.7+5

* Fixes `BuildContext` handling in example.
Expand Down
6 changes: 5 additions & 1 deletion packages/image_picker/image_picker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ When under high memory pressure the Android system may kill the MainActivity of
the application using the image_picker. On Android the image_picker makes use
of the default `Intent.ACTION_GET_CONTENT` or `MediaStore.ACTION_IMAGE_CAPTURE`
intents. This means that while the intent is executing the source application
is moved to the background and becomes eligable for cleanup when the system is
is moved to the background and becomes eligible for cleanup when the system is
low on memory. When the intent finishes executing, Android will restart the
application. Since the data is never returned to the original call use the
`ImagePicker.retrieveLostData()` method to retrieve the lost data. For example:
Expand Down Expand Up @@ -125,6 +125,10 @@ final XFile? galleryVideo =
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
// Pick multiple images.
final List<XFile> images = await picker.pickMultiImage();
// Pick singe image or video.
final XFile? media = await picker.pickMedia();
// Pick multiple images and videos.
final List<XFile> medias = await picker.pickMultipleMedia();
```

## Migrating to 0.8.2+
Expand Down
121 changes: 102 additions & 19 deletions packages/image_picker/image_picker/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:video_player/video_player.dart';

void main() {
Expand Down Expand Up @@ -38,10 +39,10 @@ class MyHomePage extends StatefulWidget {
}

class _MyHomePageState extends State<MyHomePage> {
List<XFile>? _imageFileList;
List<XFile>? _mediaFileList;

void _setImageFileListFromFile(XFile? value) {
_imageFileList = value == null ? null : <XFile>[value];
_mediaFileList = value == null ? null : <XFile>[value];
}

dynamic _pickImageError;
Expand Down Expand Up @@ -80,8 +81,12 @@ class _MyHomePageState extends State<MyHomePage> {
}
}

Future<void> _onImageButtonPressed(ImageSource source,
{required BuildContext context, bool isMultiImage = false}) async {
Future<void> _onImageButtonPressed(
ImageSource source, {
required BuildContext context,
bool isMultiImage = false,
bool isMedia = false,
}) async {
if (_controller != null) {
await _controller!.setVolume(0.0);
}
Expand All @@ -94,14 +99,42 @@ class _MyHomePageState extends State<MyHomePage> {
await _displayPickImageDialog(context,
(double? maxWidth, double? maxHeight, int? quality) async {
try {
final List<XFile> pickedFileList = await _picker.pickMultiImage(
final List<XFile> pickedFileList = isMedia
? await _picker.pickMultipleMedia(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
)
: await _picker.pickMultiImage(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_mediaFileList = pickedFileList;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
});
} else if (isMedia) {
await _displayPickImageDialog(context,
(double? maxWidth, double? maxHeight, int? quality) async {
try {
final List<XFile> pickedFileList = <XFile>[];
final XFile? media = await _picker.pickMedia(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_imageFileList = pickedFileList;
});
if (media != null) {
pickedFileList.add(media);
setState(() {
_mediaFileList = pickedFileList;
});
}
} catch (e) {
setState(() {
_pickImageError = e;
Expand Down Expand Up @@ -179,28 +212,34 @@ class _MyHomePageState extends State<MyHomePage> {
if (retrieveError != null) {
return retrieveError;
}
if (_imageFileList != null) {
if (_mediaFileList != null) {
return Semantics(
label: 'image_picker_example_picked_images',
child: ListView.builder(
key: UniqueKey(),
itemBuilder: (BuildContext context, int index) {
final String? mime = lookupMimeType(_mediaFileList![index].path);

// Why network for web?
// See https://pub.dev/packages/image_picker_for_web#limitations-on-the-web-platform
return Semantics(
label: 'image_picker_example_picked_image',
child: kIsWeb
? Image.network(_imageFileList![index].path)
: Image.file(
File(_imageFileList![index].path),
errorBuilder: (BuildContext context, Object error,
StackTrace? stackTrace) =>
const Center(
child: Text('This image type is not supported')),
),
? Image.network(_mediaFileList![index].path)
: (mime == null || mime.startsWith('image/')
? Image.file(
File(_mediaFileList![index].path),
errorBuilder: (BuildContext context, Object error,
StackTrace? stackTrace) {
return const Center(
child:
Text('This image type is not supported'));
},
)
: _buildInlineVideoPlayer(index)),
);
},
itemCount: _imageFileList!.length,
itemCount: _mediaFileList!.length,
),
);
} else if (_pickImageError != null) {
Expand All @@ -216,6 +255,17 @@ class _MyHomePageState extends State<MyHomePage> {
}
}

Widget _buildInlineVideoPlayer(int index) {
final VideoPlayerController controller =
VideoPlayerController.file(File(_mediaFileList![index].path));
const double volume = kIsWeb ? 0.0 : 1.0;
controller.setVolume(volume);
controller.initialize();
controller.setLooping(true);
controller.play();
return Center(child: AspectRatioVideo(controller));
}

Widget _handlePreview() {
if (isVideo) {
return _previewVideo();
Expand All @@ -239,7 +289,7 @@ class _MyHomePageState extends State<MyHomePage> {
if (response.files == null) {
_setImageFileListFromFile(response.file);
} else {
_imageFileList = response.files;
_mediaFileList = response.files;
}
});
}
Expand Down Expand Up @@ -300,6 +350,39 @@ class _MyHomePageState extends State<MyHomePage> {
child: const Icon(Icons.photo),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(
ImageSource.gallery,
context: context,
isMultiImage: true,
isMedia: true,
);
},
heroTag: 'multipleMedia',
tooltip: 'Pick Multiple Media from gallery',
child: const Icon(Icons.photo_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(
ImageSource.gallery,
context: context,
isMedia: true,
);
},
heroTag: 'media',
tooltip: 'Pick Single Media from gallery',
child: const Icon(Icons.photo_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Future<List<XFile?>> readmePickExample() async {
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
// Pick multiple images.
final List<XFile> images = await picker.pickMultiImage();
// Pick singe image or video.
final XFile? media = await picker.pickMedia();
// Pick multiple images and videos.
final List<XFile> medias = await picker.pickMultipleMedia();
// #enddocregion Pick

// Return everything for the sanity check test.
Expand All @@ -28,7 +32,9 @@ Future<List<XFile?>> readmePickExample() async {
photo,
galleryVideo,
cameraVideo,
if (images.isEmpty) null else images.first
if (images.isEmpty) null else images.first,
media,
if (medias.isEmpty) null else medias.first,
];
}

Expand Down
3 changes: 2 additions & 1 deletion packages/image_picker/image_picker/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ dependencies:
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
image_picker_platform_interface: ^2.6.1
image_picker_platform_interface: ^2.8.0
mime: ^1.0.4
video_player: ^2.1.4

dev_dependencies:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ class FakeImagePicker extends ImagePickerPlatform {
return <XFile>[XFile('multiImage')];
}

@override
Future<List<XFile>> getMedia({required MediaOptions options}) async {
return options.allowMultiple
? <XFile>[XFile('medias'), XFile('medias')]
: <XFile>[XFile('media')];
}

@override
Future<XFile?> getVideo(
{required ImageSource source,
Expand Down
Loading