I cant handle with image_picker. When I select a photo, I should see the photo instead of the avatar icon, but I don't know why it doesn't work that way. I'm new in flutter and maybe it should be solved in a different way.
The orange circle should stay and the icon should change, any advice will be great for me
Widget _avatar() {
return const CircleAvatar(
radius: 83,
backgroundColor: Colors.orange,
child: CircleAvatar(
backgroundColor: Colors.white,
radius: 80,
child: Icon(Icons.person_outline, size: 60, color: Colors.orange),
),
);
}
File? _image;
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(
source: ImageSource.gallery, maxWidth: 1800, maxHeight: 1800);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future getCameraImage() async {
final pickedFile = await picker.getImage(
source: ImageSource.camera,
maxWidth: 1800,
maxHeight: 1800,
);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
void _showPicker(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: Wrap(
children: <Widget>[
ListTile(
leading: new Icon(Icons.photo_size_select_large_sharp),
title: new Text('Photo Library'),
onTap: () {
getImage();
Navigator.of(context).pop();
}),
ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
getCameraImage();
Navigator.of(context).pop();
},
),
],
),
),
);
});
}
Widget _changeAvatarButton(BuildContext context) {
return Column(
children: [
CircleAvatar(
radius: 83,
backgroundColor: Colors.orange,
child: _image == null ? _avatar() : Image.file(_image!),
),
CustomButtonText(
onPressed: () {
_showPicker(context);
},
title: 'photo',
textColor: Colors.teal),
],
);
}
Change Your CircleAvtar widget with the below one and if you don't want to show the orange circle then set the backgroundColor: _image == null ? Colors.orange : Colors.transparent.
CircleAvatar(
radius: 83,
backgroundColor: Colors.orange,
child: _image == null
? _avatar()
: ClipRRect(
borderRadius: BorderRadius.circular(83),
child: Image.file(
_image!,
height: 160, // Change the size up or down accordingly border radius
width: 160, // Change the size up or down accordingly border radius
fit: BoxFit.cover,
)),
),
It looks all fine with the state update and the image picking. What you should be paying attention at is the async functions, because you need to wait for the images before updating your widgets, and getCameraImage() and getImage() are a Future. Check if adding await solves the problem.
ListTile(
leading: new Icon(Icons.photo_size_select_large_sharp),
title: new Text('Photo Library'),
onTap: () async {
await getImage();
Navigator.of(context).pop();
}),
ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () async {
await getCameraImage();
Navigator.of(context).pop();
},
),
Related
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 wanted to add 3 circle image picker avatar and wanted to upload 3 different pictures in them but unfortunately not able to do that. I tried to do this by extracting the method and passing the image to the single extracted build method and in result the chosen one image is applied to all three avatars. Kindly help me get through it.
Below are the functions for picking image from gallery and camera :
File _image;
final Picker = ImagePicker();
_imgFromCamera() async {
final image = await Picker.pickImage(
source: ImageSource.camera, imageQuality: 50
);
setState(() {
_image = File(image.path);
});
}
_imgFromGallery() async {
final image = await Picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
setState(() {
_image = File(image.path);
});
}
Next is function for bottom sheet for picking the image either from gallery or camera:
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('Photo Library'),
onTap: () {
_imgFromGallery();
Navigator.of(context).pop();
}),
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
_imgFromCamera();
Navigator.of(context).pop();
},
),
],
),
),
);
}
);
}
And here is the extracted method that I want to use for once for all three images:
GestureDetector buildGestureDetector(BuildContext context) {
return GestureDetector(
onTap: () {
_showPicker(context);
},
child: CircleAvatar(
radius: 53,
backgroundColor: Colors.black,
child: _image != null
? ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.file(
_image,
width: 100,
height: 100,
fit: BoxFit.fitHeight,
),
)
: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(50)),
width: 100,
height: 100,
child: Icon(
Icons.camera_alt,
color: Colors.grey[800],
),
),
),
);
}
}
And here is that extracted method is called inside widget :
Row(
children: [
Expanded(
child: buildGestureDetector(context),
),
],
),
Kindly help me with applying 3 different pictures using this one extracted method and all the functions used once so that I don't need to go through all this process for all three pictures again and again.
The easiest way to handle this is of course passing "which avatar" info down to _imgFromCamera or _imgFromGallery .
For example, if your 3 images have their own identities like 'A', 'B' and 'C',
onTap: () {
_showPicker(context, 'A');
},
Then pass it to the _showPicker.
void _showPicker(context, id) {
...
onTap: () {
_imgFromGallery(id); // Passed 'A' in this example
Navigator.of(context).pop();
}),
...
Then,
_imgFromGallery(id) async {
final image = await Picker.pickImage(
source: ImageSource.gallery, imageQuality: 50
);
// Depends on the id, decide where and how to save the image.
switch(id) {
case 'A': setState(...); break;
case 'B': saveIntoLocal(...); break;
case 'C': uploadToServer(...); break;
....
}
}
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
I'm Using ImagePicker and ImageCropper Package to pick and crop an image from the gallery or by capturing using a camera. Everything is working fine but the Picked image is not updating on UI even after using the SetState method. When I press the button for image Selection Again Previously selected Image Appears on the UI. I have no Idea what Is causing this delay.
My ImageProcessing Class Code
class ImageProcess{
File _image, croppedFile;
final picker = ImagePicker();
//Getting Image From Gallery Or Camera.
File getImage(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15))),
content: Container(
height: 250,
width: 250,
child: Row(
children: [
IconButton(
iconSize: 100,
icon: Icon(Icons.insert_photo),
onPressed: () async {
final pickedFile = await picker.getImage(
source: ImageSource.gallery,imageQuality: 20);
_image = File(pickedFile.path);
croppedFile = await _cropImage();
Navigator.of(context).pop(true);
}),
IconButton(
iconSize: 100,
icon: Icon(Icons.camera),
onPressed: () async {
final pickedFile =
await picker.getImage(source: ImageSource.camera,imageQuality: 20);
_image = File(pickedFile.path);
croppedFile = await _cropImage();
Navigator.of(context).pop(true);
})
],
)),
);
});
return croppedFile;
}
//Cropping image which has been retrieved from gallery or gallery.
Future<File> _cropImage() async {
return await ImageCropper.cropImage(
sourcePath: _image.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
]
: [
CropAspectRatioPreset.square,
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Product Image Cropper',
toolbarColor: kDarkYellow,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.square,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Product Image Cropper',
));
}
}
Ui code
class AddItem extends StatefulWidget {
#override
_AddItemState createState() => _AddItemState();
}
class _AddItemState extends State<AddItem> {
File croppedFile;
ImageProcess im = new ImageProcess();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: kVeryDarkBlue,
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * 0.15,
width: MediaQuery.of(context).size.height * 0.15,
child: croppedFile == null
? ClipOval(
child:
Image.asset('assets/images/image.png'))
: ClipOval(child: Image.file(croppedFile))),
RaisedButton(onPressed: () {
croppedFile= im.getImage(context);
setState(() {
});
},child: Text('Press'),)
],
),
))),
);
}
}
I have tried every possible solution which came Into My mind.
Add Future in your getImage Method with some adjusts.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: AddItem(),
);
}
}
class AddItem extends StatefulWidget {
#override
_AddItemState createState() => _AddItemState();
}
class _AddItemState extends State<AddItem> {
File croppedFile;
ImageProcess im = new ImageProcess();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.blue,
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 0),
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * 0.15,
width: MediaQuery.of(context).size.height * 0.15,
child: croppedFile == null
? ClipOval(
child: Image.asset('assets/images/image.png'))
: ClipOval(child: Image.file(croppedFile))),
RaisedButton(
onPressed: () async {
// Add await here
croppedFile = await im.getImage(context);
setState(() {});
},
child: Text('Press'),
)
],
),
))),
);
}
}
class ImageProcess {
File _image, croppedFile;
final picker = ImagePicker();
//Getting Image From Gallery Or Camera.
// now getImage is a future that wait for your choice.
Future<File> getImage(BuildContext context) async {
return await showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15))),
content: Container(
height: 250,
width: 250,
child: Row(
children: [
IconButton(
iconSize: 100,
icon: Icon(Icons.insert_photo),
onPressed: () async {
final pickedFile = await picker.getImage(
source: ImageSource.gallery, imageQuality: 20);
_image = File(pickedFile.path);
croppedFile = await _cropImage();
// croppedFile is the return of your ShowDialog
Navigator.of(context).pop(croppedFile);
}),
IconButton(
iconSize: 100,
icon: Icon(Icons.camera),
onPressed: () async {
final pickedFile = await picker.getImage(
source: ImageSource.camera, imageQuality: 20);
_image = File(pickedFile.path);
croppedFile = await _cropImage();
// croppedFile is the return of your ShowDialog
Navigator.of(context).pop(croppedFile);
})
],
)),
);
});
}
//Cropping image which has been retrieved from gallery or gallery.
Future<File> _cropImage() async {
return await ImageCropper.cropImage(
sourcePath: _image.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
]
: [
CropAspectRatioPreset.square,
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Product Image Cropper',
toolbarColor: Colors.yellow,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.square,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Product Image Cropper',
));
}
}
After Tweaking Some Lines of I have figured Out Where Was the Problem.
Code For RaisedButton In UI
RaisedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(15))),
content: Container(
height: 250,
width: 250,
child: Row(
children: [
IconButton(
iconSize: 100,
icon: Icon(Icons.insert_photo),
onPressed: () async {
croppedFile =
await im.getImageGallery();
setState(() {});
Navigator.pop(context);
}),
IconButton(
iconSize: 100,
icon: Icon(Icons.camera),
onPressed: () async {
croppedFile =
await im.getImageCamera();
setState(() {});
Navigator.pop(context);
})
],
)),
);
});
},
child: Text('Press'),
)
Code For ImageProcessing Class. I have Divided Large Function Into Two Sub Functions.
//Getting Image From Camera.
Future<File> getImageCamera() async{
final pickedFile = await picker.getImage(
source: ImageSource.camera,imageQuality: 20);
_image = File(pickedFile.path);
return _cropImage();
}
//Getting Image From Gallery
Future<File> getImageGallery() async{
final pickedFile = await picker.getImage(
source: ImageSource.gallery,imageQuality: 20);
_image = File(pickedFile.path);
return _cropImage();
}