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();
}
Related
How can I use the ImagePicker library's pickImage function in this code to replace the deprecated getImage method?How can I replace the deprecated getImage method in Flutter's Image Picker package with the pickImage method from the latest version of the package?
I am currently using the Image Picker package in my Flutter app and I recently received an error saying that the getImage method I was using has been deprecated. I've learned that it has been replaced by the pickImage method, but I'm not sure how to make the necessary changes to my code.
import 'dart:async';
import 'dart:io';
import 'package:farmassist/app_theme.dart';
import 'package:farmassist/data/diseases/classifier.dart';
import 'package:farmassist/data/diseases/disease_detection_model.dart';
import 'package:farmassist/ui/diseases/diagnosis.dart';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:logger/logger.dart';
import 'package:tflite_flutter_helper/tflite_flutter_helper.dart';
class ViewImageRegion extends StatefulWidget {
const ViewImageRegion({#required this.diagnosis});
final Diagnosis diagnosis;
#override
_ViewImageRegionState createState() => _ViewImageRegionState();
}
class _ViewImageRegionState extends State<ViewImageRegion> {
PickedFile _image;
File plantImage;
dynamic _pickImageError;
Classifier _classifier;
var logger = Logger();
Category _category;
void _onImageButtonPressed(ImageSource source, {BuildContext context}) async {
try {
final pickedFile = await ImagePicker().getImage(source: source);
_image = pickedFile;
final File _plantImage = File(_image.path);
File croppedFile = await ImageCropper.cropImage(
sourcePath: _plantImage.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9,
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false,
),
iosUiSettings: IOSUiSettings(minimumAspectRatio: 1.0),
);
plantImage = croppedFile;
_predict(_plantImage);
} catch (e) {
setState(() {
_pickImageError = e;
});
}
}
#override
void initState() {
super.initState();
_classifier = DiseaseDetectionModel();
}
void _predict(File image) async {
img.Image imageInput = img.decodeImage(image.readAsBytesSync());
var prediction = _classifier.predict(imageInput);
setState(() {
this._category = prediction;
});
if (_category.score > 0.5) {
Future.delayed(
Duration.zero,
() => widget.diagnosis.update(
_category.label, (_category.score * 100).toStringAsFixed(2)),
);
} else {
Future.delayed(
Duration.zero,
() => widget.diagnosis.update('Healthy', null),
);
}
}
void _cancelImage() {
setState(() {
plantImage = null;
});
Future.delayed(
Duration.zero,
() => widget.diagnosis.update('Disease', null),
);
}
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Column(
children: <Widget>[
Container(
height: 224.0,
width: 224.0,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 20),
borderRadius: BorderRadius.circular(18),
color: Colors.white,
),
child: Center(
child: plantImage == null
? Text(
'No image selected',
textAlign: TextAlign.center,
style: AppTheme.bodyText1,
)
: Image.file(
plantImage,
height: 224.0,
width: 225.0,
fit: BoxFit.fill,
),
),
),
Container(
height: 90.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_buildButton(
Icon(Icons.add_a_photo_outlined),
() => _onImageButtonPressed(
ImageSource.camera,
context: context,
),
),
_buildButton(
Icon(Icons.image_outlined),
() => _onImageButtonPressed(
ImageSource.gallery,
context: context,
),
),
_buildButton(
Icon(Icons.image_not_supported_outlined),
() => _cancelImage(),
),
],
),
),
],
),
),
);
}
Widget _buildButton(Icon icon, VoidCallback callback) {
return ClipOval(
child: Material(
color: Colors.white,
child: InkWell(
splashColor: Colors.lightGreenAccent[100],
child: SizedBox(
width: 56,
height: 56,
child: icon,
),
onTap: callback,
),
),
);
}
}
i am new to flutter, so I do not know how to go about it.
I am trying to compress image that is picked via file_picker package. I am compressing image with flutter_native_image. But image is not being compressed.
Where have I gone wrong?
P.S - I can't use image_picker package because it stopped working and I had to switch to file_picker.
class UploadSingleImageToFirestore extends StatefulWidget {
const UploadSingleImageToFirestore({super.key});
#override
State<UploadSingleImageToFirestore> createState() =>
_UploadSingleImageToFirestoreState();
}
class _UploadSingleImageToFirestoreState
extends State<UploadSingleImageToFirestore> {
File? _pickedImage;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarTitle(context, 'Upload Single Image'),
backgroundColor: ZayyanColorTheme.zayyanGrey,
body: _pickedImage != null
? Center(
child: Column(
children: [
ANPFormContainer(
fieldTitle: 'Single Image',
subTitle: 'Pick Single Image',
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 140),
child: Image.file(
File(_pickedImage!.path),
height: 300,
width: 300,
),
),
),
addVerticalSpacer(25),
ElevatedButton(
onPressed: () => pickImage(),
child: const Text('Pick Image')),
ElevatedButton(
onPressed: () => _updateMedia(),
child: const Text('Upload Images')),
],
),
)
: InkWell(
onTap: () => pickImage(),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.add_a_photo),
SizedBox(height: 10),
Text('Tap anywhere to pick images')
],
),
),
),
);
}
pickImage() async {
FilePickerResult? result =
await FilePicker.platform.pickFiles(type: FileType.image);
if (result != null) {
File file = File(result.files.single.path!);
print(file);
compressImage(file);
setState(() {
_pickedImage = file;
});
} else {
print("No file selected");
}
}
compressImage(path) async {
if (_pickedImage == null) return;
File compressedFile = await FlutterNativeImage.compressImage(
path,
quality: 10,
percentage: 20,
targetWidth: 600,
);
return compressedFile;
}
_updateMedia() async {
CollectionReference collectionRef =
FirebaseFirestore.instance.collection('Users');
final coverUrl = await context
.read<FirebaseStorageService>()
.saveCoverInCloudStorage(
file: _pickedImage!,
state: 'Test State',
township: 'Test Township',
propertyType: 'Test House',
propertyid: 'HYG-1234');
return collectionRef
.doc('gMH1s0XUIvWdD2fYfqMvPc915a03')
.update({
'logo': coverUrl,
})
.then((value) => ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Property Info Updated'))))
.catchError((error) => ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('+++ Failed to update user: $error"'))));
}
}
If your requirement is just images, Use image_picker instead of file_picker.
Fetching from image picker
You can use the built in imaqeQuality property from ImagePicker to compress the image. This property takes a value between 0 and 100 and represents a percentage of the original image quality.
File _image;
Future getImage() async {
var image = await ImagePicker.pickImage(
source: ImageSource.gallery,
imageQuality: 25,
);
setState(() {
_image = image;
});
}
Use flutter_native_image to compress
Future<File> compressFile(File file) async{
File compressedFile = await FlutterNativeImage.compressImage(file.path,
quality: 5,);
return compressedFile;
}
Also Refer: Flutter the best way to compress image
I want to get picutres with the emulator's camera and when i take one it' doesn't save the picture and give me an error that says pickImage method reurns a Future of type XFile and I want a return of type File and when i use (as File) it give me another Error that says Xfile is not a subtype of type File
class ImageInput extends StatefulWidget {
final Function? onSelect;
const ImageInput({Key? key, this.onSelect}) : super(key: key);
#override
_ImageInputState createState() => _ImageInputState();
}
class _ImageInputState extends State<ImageInput> {
File? _imagePicker;
Future<void> _takeAPicture() async {
final picker = ImagePicker();
final imageFile = await picker.pickImage(
source: ImageSource.gallery,
maxWidth: 600,
);
}
Future<void> _chooseAPicture() async {
final picker = ImagePicker();
final imageFile = await picker.pickImage(
source: ImageSource.camera,
maxWidth: 600,
) as File;
setState(() {
_imagePicker = File(imageFile.path);
});
final appdir = await syspath.getApplicationDocumentsDirectory();
final fileName = path.basename(imageFile.path);
final savedImage = await imageFile.copy('${appdir.path}/${fileName}');
widget.onSelect!(savedImage);
}
#override
Widget build(BuildContext context) {
return Row(children: [
Container(
child: _imagePicker != null
? Image.file(
_imagePicker as File,
fit: BoxFit.cover,
width: double.infinity,
)
: Text(
'No Image Taken',
textAlign: TextAlign.center,
),
alignment: Alignment.center,
height: 100,
width: 100,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1),
),
),
SizedBox(
height: 10,
),
Expanded(
child: Column(
children: [
TextButton.icon(
onPressed: () => _takeAPicture(),
label: Text('choose an Image'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
TextStyle(color: Theme.of(context).primaryColor),
),
),
icon: Icon(Icons.camera),
),
TextButton.icon(
onPressed: () => _chooseAPicture(),
label: Text('Take an Image'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
TextStyle(color: Theme.of(context).primaryColor),
),
),
icon: Icon(Icons.camera_enhance_sharp),
),
],
),
),
]);
}
}
Try out below code for XFile
final ImagePicker _picker = ImagePicker();
Future getForFrontImage(ImageSource source) async {
final XFile? pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
selectedChequeImg = File(pickedFile.path);
});
}
}
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();
},
),
I got some problem with _showSnackbar I see following error:
Exception has occurred.
NoSuchMethodError (NoSuchMethodError: The method 'showSnackBar'
was called on null.Receiver: null
Tried calling: showSnackBar(Instance of 'SnackBar'))
But I'm sure I already created GlobalKey for ShowSnackbar :
final _scaffoldKey = GlobalKey<ScaffoldState>();
This is my function showsnackbar
void _showSnackBar(BuildContext context, String message, Color color) {
final snackBar = SnackBar(
duration: Duration(seconds: 1),
backgroundColor: color,
content: Text(message),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
This is how I call the showsnackbar
upload != 0 ? _showSnackBar(context,"Success Upload",Colors.green) : _showSnackBar(context,"Success Upload",Colors.green);
And this is the full source code my view
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
#override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImageRevisi(_image,_txtNameImage);
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImageRevisi(File imageFile, TextEditingController _txtName) async{
int upload = await api.uploadImageRevisi(imageFile,_txtName);
upload != 0 ? _showSnackBar(context,"Success Upload",Colors.green) : _showSnackBar(context,"Success Upload",Colors.green);
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
void _showSnackBar(BuildContext context, String message, Color color) {
final snackBar = SnackBar(
duration: Duration(seconds: 1),
backgroundColor: color,
content: Text(message),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
Did I make a mistake somewhere?
Thanks
You've forgot to set key property:
return Scaffold(
key: _scaffoldKey ...