I have built an AlertDialog widget to allow users to upload photos from the gallery or the camera.
This widget will be used in multiple places throughout the app so I wanted to refactor it into a reusable widget, but I am stuck on how to proceed. The issue I’m facing is that I need to do different things with the resulting image, so I’m looking for a way to have the AlertDialog widget return the image back to the calling parent widget.
Ideas would be much appreciated!
Example of triggering the AlertDialog widget on tap:
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Attach Photo'),
actions: [
RadioListTile(
title: Text('Camera'),
value: 1,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: true)
.then((image) {
// Do things with image here
});
},
),
RadioListTile(
title: Text('Gallery'),
value: 2,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: false)
.then((image) {
// Do things with image here
});
},
),
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text(
'Cancel',
style: TextStyle(
fontSize: 15,
),
),
),
],
);
});
}
Code for the getImage helper function:
// ImagePicker to get photo from gallery or camera
Future<File?> getImage({required bool fromCamera}) async {
final ImagePicker _picker = ImagePicker();
final ImageSource _source =
fromCamera ? ImageSource.camera : ImageSource.gallery;
final XFile? image = await _picker.pickImage(source: _source);
if (image != null) {
return File(image.path);
}
}
>Solution :
I would just add another global Function
Future showImageDialog(Function(Image?) onImagePicked)
=> showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Attach Photo'),
actions: [
RadioListTile(
title: Text('Camera'),
value: 1,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: true)
.then((image) {
onImagePicked(image);
});
},
),
RadioListTile(
title: Text('Gallery'),
value: 2,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: false)
.then((image) {
onImagePicked(image);
});
},
),
TextButton(
onPressed: () {
onImagePicked(null);
Navigator.pop(context),
}
child: const Text(
'Cancel',
style: TextStyle(
fontSize: 15,
),
),
),
],
);
});
or just use Navigator.pop
Future<Image?> showImageDialog()
=> showDialog<Image?>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Attach Photo'),
actions: [
RadioListTile(
title: Text('Camera'),
value: 1,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: true)
.then((image) {
Navigator.of(context).pop(image);
});
},
),
RadioListTile(
title: Text('Gallery'),
value: 2,
groupValue: 3,
onChanged: (int? value) {
Navigator.pop(context);
Helper.of(context)
.getImage(fromCamera: false)
.then((image) {
Navigator.of(context).pop(image);
});
},
),
TextButton(
onPressed: () {
Navigator.of(context).pop(null);
},
child: const Text(
'Cancel',
style: TextStyle(
fontSize: 15,
),
),
),
],
);
});