how to preview an image is to be chosen from gallery or camera in flutter with the new version of image_picker where
PickedFile image = await _picker.getImage(...)
is replace with
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
so photo must be displayed when it is selected properly
You can do it by using dialog in flutter.
Here is how I dealt with it.
onLongPress: () {
showDialog(
context: context,
builder: (ctx) {
final width = ctx.getWidth(1);
final height = ctx.getHeight(1);
return AlertDialog(
content: Stack(
children: [
SizedBox(
width: width * 0.9,
height: height * 0.7,
child: Image.network(
food.imageUrl,
fit: BoxFit.fill,
),
),
GestureDetector(
onTap: () => Navigator.pop(context),
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
shape: BoxShape.circle),
child: Icon(
CupertinoIcons.xmark_circle,
color: Colors.white.withOpacity(0.9),
size: 40,
),
),
),
)
],
),
insetPadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
clipBehavior: Clip.antiAliasWithSaveLayer,
);
},
);
},
You can preview image which you select from gallery or camera as below :
Image.file(
File("file path will be here"), // You can access it with . operator and path property
fit: BoxFit.cover,
)
convert to file:
File newPhoto = File(photo.path);
Use:
Image.file(newPhoto);
I used image_pickers package much easier
late File imageFile = File("");
bool isloaded = false;
ElevatedButton(
onPressed: () => pickImageFromCamera(),)
Padding(
padding: const EdgeInsets.all(8.0),
child: !isloaded
? Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/No_image_available.svg/2048px-No_image_available.svg.png")
: Image.file(imageFile)),
void pickImageFromCamera() async {
List<Media>? res = await ImagesPicker.openCamera(
pickType: PickType.image,
);
print(res);
if (res != null) {
print(res[0].path);
setState(() {
imageFile = File(res[0].path);
isloaded = true;
setState(() {});
});
} else {
setState(() {
isloaded = false;
});
}
}
Related
How can I display a Carousel framed by taking pictures in the moment?
This carousel needs a function to remove photos if needed. And an indicator of what image I'm seeing.
I'm using packages: 'image_picker' to get the photos from gallery or camera. And the 'carousel_slider' package to display the carousel.
And so, if there isn't a photo there isn't a carousel.
The problem I get is that the second photo replaces the first... the third replaces the second and the first, I mean the next photo will replace the previous photos. Also, I can't remove the photos from the carousel, and I can't display the indicators for the image I'm looking at either.
Here are the functions I run to take the pictures:
_takePicture() async {
File auxiliarFile;
final ImagePicker _picker = ImagePicker();
XFile imageFile = await _picker.pickImage(
source: ImageSource.camera, maxWidth: 600) as XFile;
setState(() {
_storedImage = File(imageFile.path);
});
auxiliarFile = _storedImage!;
final appDir = await syspath.getApplicationDocumentsDirectory();
String fileName = path.basename(_storedImage!.path);
final savedImage = await _storedImage!.copy('${appDir.path}/$fileName');
listImages.add(auxiliarFile);
}
_chosePicture() async {
final ImagePicker _picker = ImagePicker();
XFile imageFile = await _picker.pickImage(
source: ImageSource.gallery,
) as XFile;
setState(() {
_storedImage = File(imageFile.path);
});
final appDir = await syspath.getApplicationDocumentsDirectory();
String fileName = path.basename(_storedImage!.path);
final savedImage = await _storedImage!.copy('${appDir.path}/$fileName');
listImages.add(savedImage);
}
To display the carousel I tried:
_storedImage != null
? Column(
children: [
CarouselSlider(
options: CarouselOptions(
enableInfiniteScroll: false,
enlargeCenterPage: true,
enlargeFactor: 0.25,
),
items: listImages.map((i) {
return Builder(builder:
(BuildContext context) {
return Container(
width: MediaQuery.of(context)
.size
.width *
0.75,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
border: Border.all(
color: Colors.black87),
color: Colors.grey[350],
),
child: OutlinedButton(
onPressed: _showDeleteDialog,
onLongPress: () =>
_showDeleteDialog(),
child: Image.file(
(_storedImage!),
),
),
);
});
}).toList(),
),
Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: map<Widget>(listImages,
(index, url) {
return InkWell(
onTap: () {
setState(() {
_pageController
.jumpToPage(index);
currentIndex = index;
});
},
child: Container(
width: 10,
height: 10,
margin: const EdgeInsets
.symmetric(
vertical: 10,
horizontal: 5,
),
decoration:
const BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey,
),
),
);
}),
),
),
],
)
: const Text(
'No image',
style: TextStyle(
fontWeight: FontWeight.bold,
),
)
I have created a variable
List<Xfile> imageList;
using this variable I have showed the selected images in GridView.Builder and uploaded them.
But I want to store those uploaded images in this List to show them again in GridView.Builder.
Means How to store images from imageUrls in List
How can I achieve this?
Follow as follows:
Variables
final picker = ImagePicker();
File? file;
XFile? pickedImage;
bool isLoading = false;
List<File?> fileList = [];
Method to select image from gallery
Future pickImageFromGallery() async {
pickedImage = await picker.pickImage(source: ImageSource.gallery);
setState(() {
file = File(pickedImage!.path);
fileList.add(file);
});
}
And place in gridview as follows:
GridView.builder(
itemCount: fileList.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int i) {
return Container(
padding: const EdgeInsets.all(10),
child: Stack(
children: <Widget>[
SizedBox(
height: 100,
width: 100,
child: Image.file(File(fileList[i]!.path),fit: BoxFit.cover,),
),
Positioned(
right: 1,
child: GestureDetector(
onTap: () {
setState(() {
dltImages(fileList[i]);
});
},
child: const Icon(Icons.cancel, color: Colors.red),
))
],
),
);
},
),
Find full code at:
https://github.com/nbnD/image_picker_flutter/blob/master/lib/homepage.dart
I do like this if there is multi images upload
class PickImagesPage extends StatefulWidget {
const PickImagesPage({super.key, required this.initialUrls});
final List<String> initialUrls;
#override
State<PickImagesPage> createState() => _PickImagesPageState();
}
class _PickImagesPageState extends State<PickImagesPage> {
#override
void initState() {
urls = widget.initialUrls;
super.initState();
}
List<String> urls = [];
List<File> files = [];
List<String> removedUrls = [];
final Repo repo = Repo();
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final style = theme.textTheme;
final scheme = theme.colorScheme;
return LoadingLayer(
child: Scaffold(
bottomNavigationBar: Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 24),
child: ElevatedButton(
onPressed:
files.isNotEmpty || widget.initialUrls.length != urls.length
? () async {
try {
await repo.uploadImages(
files: files,
urls: urls,
removedUrls: removedUrls,
);
Navigator.pop(context);
} catch (e) {
AppSnackbar(context).error(e);
if (kDebugMode) {
print(e);
}
}
}
: null,
child: const Text(Labels.save),
),
),
appBar: AppBar(
title: const Text(
Labels.ambienceImages,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final List<XFile> pickedFiles = await pickImages();
if (pickedFiles.isNotEmpty) {
setState(() {
files.addAll(pickedFiles.map((e) => File(e.path)));
});
}
},
child: const Icon(Icons.add),
),
body: GridView.count(
padding: const EdgeInsets.all(12),
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
children: [
...urls
.map(
(e) => GestureDetector(
onTap: () {
setState(() {
urls.remove(e);
removedUrls.add(e);
});
},
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage(e),
),
),
),
),
)
.toList(),
...files
.map(
(e) => Container(
clipBehavior: Clip.antiAlias,
alignment: Alignment.topRight,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: FileImage(e),
),
),
child: SizedBox(
height: 40,
width: 40,
child: RawMaterialButton(
elevation: 0,
focusElevation: 0,
hoverElevation: 0,
shape: const CircleBorder(),
fillColor: theme.cardColor.withOpacity(0.5),
onPressed: () {
setState(() {
files.remove(e);
});
},
child: const Icon(Icons.remove),
),
),
),
)
.toList(),
GestureDetector(
onTap: () async {
final List<XFile> pickedFiles = await pickImages();
if (pickedFiles.isNotEmpty) {
setState(() {
files.addAll(pickedFiles.map((e) => File(e.path)));
});
}
},
child: Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: scheme.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(20),
),
child: Stack(
children: const [
Center(
child: Icon(Icons.add),
),
PickImageLabel(),
],
),
),
),
],
),
),
);
}
}
class Repo {
Future<void> uploadImages(
{required List<String> urls,
required List<File> files,
required List<String> removedUrls}) async {
List<String> newUrls = [];
for (var file in files) {
final url = await upload(file);
newUrls.add(url);
}
for (var url in removedUrls) {
await deleteImage(url);
}
await saveImages(urls + newUrls);
}
}
I'm trying to find a solution for resizing an image.
The images are picked from a gallery or camera. The problem that I have Is that the image always is not sharp.
This Is How I pick the photo
void _showPickOptionsDialog(BuildContext context, UserData userData) {
final user = Provider.of<Userforid>(context, listen: false);
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text("Pick From Gallery"),
onTap: () {
_loadPicker(ImageSource.gallery, userData);
Navigator.pop(context);
},
),
ListTile(
title: Text("Pick from Camera"),
onTap: () {
_loadPicker(ImageSource.camera, userData);
Navigator.pop(context);
},
),
],
),
),
);
}
Future _loadPicker(ImageSource source, UserData userData) async {
final XFile file =
await picker.pickImage(source: source, imageQuality: 100);
if (this.mounted) {
// This checks if the widget is still in the tree
setState(() {
if (file != null) {
_cropImage(file, userData);
} else {
return null;
}
});
//Navigator.pop(context);
}
}
_cropImage(XFile picked, UserData userData) async {
final user = FirebaseAuth.instance.currentUser.uid;
File cropped = await ImageCropper.cropImage(
sourcePath: picked.path,
aspectRatioPresets: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio16x9,
CropAspectRatioPreset.ratio5x4
],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
if (_pickedImage != null) {
final ref = FirebaseStorage.instance
.ref()
.child('user_profile_pictures')
.child(user + '.jpg');
await ref.putFile(_pickedImage);
final url = await ref.getDownloadURL();
_curenturl = url;
await DatbaseService(uid: user).updateUserData(
...);
}
}
And this is how I display them
Container(
child: ClipRRect(
borderRadius:
BorderRadius.circular(60),
child: Container(
height: 110,
width: 110,
decoration: BoxDecoration(
color: Colors.white,
),
child: _pickedImage != null
? Image.file(
_pickedImage,
fit: BoxFit.cover,
)
: userData.url != null &&
userData.url !=
"profilepictureer"
? Image.network(
userData.url,
fit: BoxFit.cover,
)
: Image.asset(
'assets/profilepictureer.png') // Your widget is here when image is no available.
),
),
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: new Border.all(
color: Colors.black,
width: 1)),
),
So the images are set as user profile photos. Probably a solution will be to upload rounded images like Instagram. So the question that I have is how can a user picks a normal photo from camera or gallery and upload it as rounded?
If not how to solve ghe problem then?
You can simply wrap the widget with a ClipOval with flutter.
Take a look at this doc: Flutter Document
or Try using BoxFit.fill
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
userData.url,
fit: BoxFit.fill,
),
Hey I am using a method for picking photos for user profile picture like that
void _showPickOptionsDialog(BuildContext context, UserData userData) {
final user = Provider.of<Userforid>(context, listen: false);
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
title: Text("Pick From Gallery"),
onTap: () {
_loadPicker(ImageSource.gallery, userData);
Navigator.pop(context);
},
),
ListTile(
title: Text("Pick from Camera"),
onTap: () {
_loadPicker(ImageSource.camera, userData);
Navigator.pop(context);
},
),
],
),
),
);
}
Future _loadPicker(ImageSource source, UserData userData) async {
final XFile file =
await picker.pickImage(source: source, imageQuality: 100);
if (this.mounted) {
// This checks if the widget is still in the tree
setState(() {
if (file != null) {
_cropImage(file, userData);
} else {
return null;
}
});
//Navigator.pop(context);
}
}
_cropImage(XFile picked, UserData userData) async {
final user = FirebaseAuth.instance.currentUser.uid;
File cropped = await ImageCropper.cropImage(
sourcePath: picked.path,
aspectRatioPresets: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio16x9,
CropAspectRatioPreset.ratio5x4
],
maxWidth: 800,
);
if (cropped != null) {
setState(() {
_pickedImage = cropped;
});
}
if (_pickedImage != null) {
final ref = FirebaseStorage.instance
.ref()
.child('user_profile_pictures')
.child(user + '.jpg');
await ref.putFile(_pickedImage);
final url = await ref.getDownloadURL();
_curenturl = url;
await DatbaseService(uid: user).updateUserData(
...);
}
}
And then I displaying the image like that
Container(
child: ClipRRect(
borderRadius:
BorderRadius.circular(60),
child: Container(
height: 110,
width: 110,
decoration: BoxDecoration(
color: Colors.white,
),
child: _pickedImage != null
? Image.file(
_pickedImage,
fit: BoxFit.cover,
)
: userData.url != null &&
userData.url !=
"profilepictureer"
? Image.network(
userData.url,
fit: BoxFit.cover,
)
: Image.asset(
'assets/profilepictureer.png') // Your widget is here when image is no available.
),
),
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: new Border.all(
color: Colors.black,
width: 1)),
),
So a user picks a photo then he can choose if he wanna crop the image and then im creating a downloadurl which im uploading into cloud firestorm and finally uploading the image into firebase cloud storage.
When ever I wanna display the photo I just calling the url.
The problem that I have is that the image looks pixaled and not sharp.
Like this
Hope anyone can help.
My 2 cents
First, try downloading the image directly from the online storage to your computer to check if it was corrupted during the upload.
Next, use the CircleAvatar widget to check whether the problem is not with the displaying part.
CircleAvatar(
radius: 50.0,
backgroundImage: _pickedImage,
)
I am trying to enable to the app user to change his/her profile picture and upload it via camera or gallery, I used
the image picker package for this purpose,
this is my code snippet:
`
class ProfilePic extends StatefulWidget {
const ProfilePic({
Key key,
}) : super(key: key);
#override
_ProfilePicState createState() => _ProfilePicState();
}
class _ProfilePicState extends State<ProfilePic> {
File image = new File("");
final _picker = ImagePicker();
#override
Widget build(BuildContext context) {
return SizedBox(
height: 115,
width: 115,
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: [
CircleAvatar(
backgroundImage: AssetImage(image.uri.toFilePath()),
// child: ClipRRect(
// borderRadius: BorderRadius.circular(50),
// child: image != null
// ? Image.file(
// image,
// width: 115,
// height: 115,
// fit: BoxFit.fitHeight,
// )
// : Container(
// decoration: BoxDecoration(
// color: Colors.grey[100],
// borderRadius: BorderRadius.circular(50)),
// width: 100,
// height: 100,
// child: Icon(
// Icons.camera_alt,
// color: Colors.grey[800],
// ),
// ),
// ),
),
Positioned(
right: -16,
bottom: 0,
child: SizedBox(
height: 46,
width: 46,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
side: BorderSide(color: Colors.white),
),
color: Color(0xFFF5F6F9),
onPressed: () {
_showPicker(context);
},
child: SvgPicture.asset("icons/cameraIcon.svg"),
),
),
)
],
),
);
}
_imgFromCamera() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.camera, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
_imgFromGallery() async {
PickedFile pickedFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
setState(() {
image = File(pickedFile.path);
});
}
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_library),
title: new Text('Gallerie'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Caméra'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
});
}
}
`
PS: I am using Chrome for debugging.
Its select the image from the device but doesn't change the state to upload the image, am asking if it is a flutter web related problem so in a real device or emulator can work smoothly?
Any suggestion please.
AssetImage takes asset files that you have referenced in your pubspec.yaml. you should use FileImage instead if you are trying to display images from the camera or gallery.
example: FileImage(image)
You can read more here