how to show selected image in alert dialog? - flutter

I want to implement that after clicking upload button it will pick image from gallery. After picking image then open Image cropper screen lastly cropped image will show in alert dialog. But here clicking upload button it pick image again clicking upload button open crop screen lastly clicking upload button it shows alert dialog.i want to change state automatically .. How can i fix that. Here is a sample code i have tried
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 {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late AppState state;
File? imageFile;
#override
void initState() {
super.initState();
state = AppState.free;
}
#override
Widget build(BuildContext context) {
Future pickedImage() async {
final pickedImage =
await ImagePicker().pickImage(source: ImageSource.gallery);
imageFile = pickedImage != null ? File(pickedImage.path) : null;
if (imageFile != null) {
setState(() {
state = AppState.picked;
});
}
}
Future<Null> _cropImage() async {
var croppedFile = await ImageCropper().cropImage(
sourcePath: imageFile!.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
]
: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio5x3,
CropAspectRatioPreset.ratio5x4,
CropAspectRatioPreset.ratio7x5,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Cropper',
));
if (croppedFile != null) {
imageFile = croppedFile;
setState(() {
state = AppState.cropped;
});
}
}
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () {
if (state == AppState.free)
pickedImage();
else if (state == AppState.picked)
_cropImage();
else if (state == AppState.cropped) {
showAlertDialog(context);
} else {
Container();
}
},
child: Text("Upload"))
],
));
}
showAlertDialog(BuildContext context) {
// Create button
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
// Create AlertDialog
AlertDialog alert = AlertDialog(
title: Text("Simple Alert"),
content: Container(
width: 250,
height: 100,
child: imageFile != null ? Image.file(imageFile!) : Container(),
),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
enum AppState {
free,
picked,
cropped,
}

Maybe you should add this line to setState block also.
if (croppedFile != null) {
//imageFile = croppedFile;
setState(() {
imageFile = croppedFile; //to here
state = AppState.cropped;
});
}

ImagePicker return a nullable CroppedFile?.
You can create a state variable to hold it.
File? imageFile;
CroppedFile? croppedFile;
/// you can also directly assing it on `croppedFile = await ImageCropper().cropImage(`
if (croppedFile != null) {
croppedFile = croppedFile;
setState(() {
state = AppState.cropped;
});
}
Now to view the croppedFile
croppedFile != null ? Image.file(File(croppedFile!.path)) : null),

Related

image_picker It does not allow me to load an image from gallery or camera

Everything works normally, but when I click to load an image from the gallery or from the camera, it does not load the image
The message in the VSC Debug Console is:
D/MediaScannerConnection( 5069): Scanned /data/user/0/com.lot.sig/cache/ce7735c2-8d36-4633-996f-bfae03424df26527509175807023631.jpg to null
This is my user_profile.dart:
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
class UserProfile extends StatefulWidget {
UserProfile();
#override
_UserProfile createState() => _UserProfile();
}
enum AppState {
free,
picked,
cropped,
}
class _UserProfile extends State<UserProfile> {
AppState? state;
File? imageFile;
#override
void initState() {
super.initState();
state = AppState.free;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black87,
title: Text("Hola"),
),
body: Center(
child: imageFile != null ? Image.file(imageFile!) : Container(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black87,
onPressed: () {
if (state == AppState.free)
_pickImage();
else if (state == AppState.picked)
_cropImage();
else if (state == AppState.cropped) _clearImage();
},
child: _buildButtonIcon(),
),
);
}
Widget _buildButtonIcon() {
if (state == AppState.free)
return Icon(Icons.add);
else if (state == AppState.picked)
return Icon(Icons.crop);
else if (state == AppState.cropped)
return Icon(Icons.clear);
else
return Container();
}
Future<Null> _pickImage() async {
final _imageFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (_imageFile != null) {
imageFile = File(_imageFile.path);
setState(() {
state = AppState.picked;
});
}
}
Future<Null> _cropImage() async {
File? croppedFile = await ImageCropper.cropImage(
sourcePath: imageFile!.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
]
: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio5x3,
CropAspectRatioPreset.ratio5x4,
CropAspectRatioPreset.ratio7x5,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Cropper',
));
if (croppedFile != null) {
imageFile = croppedFile;
setState(() {
state = AppState.cropped;
});
}
}
void _clearImage() {
imageFile = null;
setState(() {
state = AppState.free;
});
}
}
And this is my image_picker_handler.dart :
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:sig/utilitary/image_picker_dialog.dart';
class ImagePickerHandler {
late ImagePickerDialog imagePicker;
AnimationController? _controller;
ImagePickerListener _listener;
ImagePickerHandler(this._listener, this._controller);
final ImagePicker _picker = ImagePicker();
openCamera() async {
imagePicker.dismissDialog();
var image = await (_picker.pickImage(source: ImageSource.camera) as FutureOr<XFile>);
cropImage(image);
}
openGallery() async {
imagePicker.dismissDialog();
var image = await (_picker.pickImage(source: ImageSource.gallery) as FutureOr<XFile>);
cropImage(image);
}
void init() {
imagePicker = new ImagePickerDialog(this, _controller);
imagePicker.initState();
}
Future cropImage(XFile image) async {
File? croppedFile = await ImageCropper.cropImage(
sourcePath: image.path,
maxWidth: 512,
maxHeight: 512,
);
_listener.userImage(croppedFile);
}
showDialog(BuildContext context) {
imagePicker.getImage(context);
}
}
abstract class ImagePickerListener {
userImage(File? _image);
}

flutter) There's a problem with using imagePicker

I'm using sdk 2.12.0 and image_picker 0.8.4 version.
I'm going to link my gallery to get an image.
However, when I press the Add Image button on my app, the app turns off immediately.
This is the code for the image_picker I used.
class CreatePage extends StatefulWidget {
const CreatePage({Key? key, required this.user}) : super(key: key);
final User user;
#override
_CreatePageState createState() => _CreatePageState();
}
class _CreatePageState extends State<CreatePage> {
//ImagePicker
final ImagePicker _picker = ImagePicker();
File? _imageFile;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppbar(),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: _getImage,
backgroundColor: Colors.blue,
child: Icon(Icons.add_a_photo),
),
);
}
Future<void> _getImage() async {
//ImagePiker
var image = await _picker.pickImage(source: ImageSource.gallery);
setState(() {
_imageFile = File(image!.path);
});
}
And this is my full code about this page. (Firebase code is included)
import 'dart:io';
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class CreatePage extends StatefulWidget {
//user info
const CreatePage({Key? key, required this.user}) : super(key: key);
final User user;
#override
_CreatePageState createState() => _CreatePageState();
}
class _CreatePageState extends State<CreatePage> {
//input text
final TextEditingController createText = TextEditingController();
//ImagePicker
final ImagePicker _picker = ImagePicker();
File? _imageFile;
//_createPageState가 제거될 때 호출됨
#override
void dispose() {
// TODO: implement dispose
createText.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: _buildAppbar(),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: _getImage,
backgroundColor: Colors.blue,
child: Icon(Icons.add_a_photo),
),
);
}
_buildAppbar() {
return AppBar(
actions: [
IconButton(
icon: Icon(Icons.send),
onPressed: () {
_uploadPost(context);
},
),
],
);
}
_buildBody() {
return SingleChildScrollView(
child: Column(
children: [
_imageFile == null ? Text("No Image") : Image.file(_imageFile!),
TextField(
controller: createText,
decoration: InputDecoration(
hintText: "내용을 입력하세요",
),
)
],
),
);
}
//gallery image
Future<void> _getImage() async {
var image = await _picker.pickImage(source: ImageSource.gallery);
setState(() {
_imageFile = File(image!.path);
});
}
Future _uploadPost(BuildContext context) async {
final firebaseStorageRef = FirebaseStorage.instance
.ref()
.child('post')
.child('${DateTime.now().microsecondsSinceEpoch}.png');
final task = await firebaseStorageRef.putFile(
_imageFile!, SettableMetadata(contentType: "image/png")
);
final uri = await task.ref.getDownloadURL();
//database document
final doc = FirebaseFirestore.instance.collection('post').doc();
//json type
await doc.set({
'id': doc.id,
'photoUrl': uri.toString(), //storage file url
'contents': createText, //user input text
'email': widget.user.email, //user email
'displayName': widget.user.displayName, //user name
'userPhotoUrl': widget.user.photoURL, //user profile image
});
//return page
Navigator.pop(context);
}
}
Pressing the floatingActionButton turns off the app and outputs the following error.
Lost connection to device.
May I know the cause of this?
Thank you in advance.
try adding dependency
image_picker: ^0.8.3+2
import 'package:image_picker/image_picker.dart';
then add this code
String url = "";
ImagePicker image = ImagePicker();
File ? file;
getImage() async {
var img = await image.pickImage(source: ImageSource.gallery);
setState(() {
file = File(img!.path);
});
}
And add:
onTap: () {
getImage();
},
add code:
child: file != null ?
Column(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
color: Colors.black,
margin: EdgeInsets.only(top: 80),
width: double.infinity,
height: 250,
child: Image.file(
file!,
fit: BoxFit.contain,
),
),
),
My guess is that you don't have permission to access the Media on the device, thus aborting the app the moment you try to do so. Check out the permission handler package.

Cannot load image with flutter image_editor_pro

I want to use this package. But I seem to be missing something. This is my code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return HomePage().xMaterialApp();
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
File _image = File("assets/images/butterfly.jpg");
Future<void> getimageditor() =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ImageEditorPro(
appBarColor: Colors.blue,
bottomBarColor: Colors.blue,
);
})).then((geteditimage) {
if (geteditimage != null) {
setState(() {
_image = geteditimage;
});
}
}).catchError((er) {
print(er);
});
#override
Widget build(BuildContext context) {
return condition(
condtion: _image == null,
isTue: 'Open Editor'.text().xRaisedButton(
onPressed: () {
getimageditor();
},
).toCenter(),
isFalse: Image.file(_image).toCenter())
.xScaffold(
appBar: 'Image Editor Pro example'.xTextColorWhite().xAppBar(),
floatingActionButton:
Icons.add.xIcons().xFloationActiobButton(color: Colors.red));
}
}
Widget condition({bool condtion, Widget isTue, Widget isFalse}) {
return condtion ? isTue : isFalse;
}
error: Cannot open file, path = 'assets/images/butterfly.jpg' (OS Error: No such file or directory, errno = 2).
How am I supposed to load an image with this?
I even tried to use Image from the get go. But no result. Maybe I am doing the File to Image conversion wrong?
**Update 1: **
class _HomePageState extends State<HomePage> {
final image = Image.asset('assets/images/butterfly.jpg');
Future<void> getimageditor() =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ImageEditorPro(
appBarColor: Colors.blue,
bottomBarColor: Colors.blue,
);
})).then((geteditimage) {
if (geteditimage != null) {
setState(() {
image = geteditimage; // shows error asking to make the field not final
});
}
}).catchError((er) {
print(er);
});
#override
Widget build(BuildContext context) {
return condition(
condtion: image == null,
isTue: 'Open Editor'.text().xRaisedButton(
onPressed: () {
getimageditor();
},
).toCenter(),
isFalse: Image.file(image).toCenter()) //The argument type 'Image' can't be assigned to the parameter type 'File'.
.xScaffold(
appBar: 'Image Editor Pro example'.xTextColorWhite().xAppBar(),
floatingActionButton:
Icons.add.xIcons().xFloationActiobButton(color: Colors.red));
}
}
You need to add your asset directories to your pubspec.yaml.
For example:
dependencies:
...
dev_dependencies:
...
flutter:
uses-material-design: true
assets:
- assets/
- assets/images/
Then you can read the file as an image like so:
final image = Image.asset('assets/images/butterfly.jpg');
If you need to read the image as a file for the package you are trying to use, instead of coding in images, use a package like image_picker.
For your case:
class _HomePageState extends State<HomePage> {
File _image;
final picker = ImagePicker();
Future<void> getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future<void> getimageditor() =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ImageEditorPro(
appBarColor: Colors.blue,
bottomBarColor: Colors.blue,
);
})).then((geteditimage) {
if (geteditimage != null) {
setState(() {
_image = geteditimage;
});
}
}).catchError((er) {
print(er);
});
#override
Widget build(BuildContext context) {
return condition(
condtion: _image == null,
isTue: 'Open Editor'.text().xRaisedButton(
onPressed: () async {
await getImage();
await getimageditor();
},
).toCenter(),
isFalse: Image.file(_image).toCenter())
.xScaffold(
appBar: 'Image Editor Pro example'.xTextColorWhite().xAppBar(),
floatingActionButton:
Icons.add.xIcons().xFloationActiobButton(color: Colors.red));
}
}
Widget condition({bool condtion, Widget isTue, Widget isFalse}) {
return condtion ? isTue : isFalse;
}
Solution for this is error is to prevent the Image.file to read from null by setting a null check:
_image == null ? Container() : Image.file(_image).toCenter())
The app will build without error, and after that you can use the image editor pro to edit your image.
If anyone wants to pass image to editor page from image picker :
make changes to image_editor_pro.dart file
final Color appBarColor;
final Color bottomBarColor;
final Directory pathSave;
final double pixelRatio;
final File image;
ImageEditorPro(
{this.appBarColor,
this.bottomBarColor,
this.pathSave,
this.pixelRatio,
this.image});
#override
void initState() {
timers();
_controller.clear();
type.clear();
// fontsize.clear();
offsets.clear();
// multiwidget.clear();
howmuchwidgetis = 0;
_image = widget.image;
super.initState();
}
**Then use this code **
import 'package:flutter/material.dart';
import 'dart:io';
// ignore: import_of_legacy_library_into_null_safe
import 'package:image_editor_pro/image_editor_pro.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:firexcode/firexcode.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return HomePage().xMaterialApp();
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
File? _image;
final picker = ImagePicker();
Future<void> getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
// ignore: unnecessary_null_comparison
if (pickedFile != null) {
_image = File(pickedFile.path);
print("images : $_image");
} else {
print('No image selected.');
}
});
}
Future<void> getimageditor() async {
// ignore: unused_local_variable
final geteditimage =
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ImageEditorPro(
appBarColor: Colors.blue,
bottomBarColor: Colors.blue,
image: _image,
);
})).then((geteditimage) {
print("image : $geteditimage");
if (geteditimage != null) {
setState(() {
_image = geteditimage;
});
}
}).catchError((er) {
print(er);
});
}
#override
Widget build(BuildContext context) {
return condition(
// ignore: unnecessary_null_comparison
condtion: _image == null,
isTrue: 'Open Editor'.text().xRaisedButton(
onPressed: () async {
await getImage();
await getimageditor();
},
).toCenter(),
isFalse:
// ignore: unnecessary_null_comparison
_image == null ? Container() : Image.file(_image!).toCenter())
.xScaffold(
appBar: 'Image Editor Pro example'.xTabText().xAppBar(),
floatingActionButton:
Icons.add.xIcons().xFloationActiobButton(color: Colors.red))
.xRaisedButton(onPressed: () {
getimageditor();
});
}
}
Widget? condition({required bool condtion, Widget? isTrue, Widget? isFalse}) {
return condtion ? isTrue : isFalse;
}

How to save perticular part of the screen as image in flutter

I have list of images of answer sheet in server.I need to display that images and need to select some particular area of that image, and save only that area as image. I done displaying and selection part but i don't know how to save only that selected area as image. please help me as soon as possible.
import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'dart:io';
import 'package:http/http.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
primaryColor: Colors.red,
scaffoldBackgroundColor: Colors.white,
canvasColor: Colors.transparent),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
List<AnswerSheet> answerSheets = [
AnswerSheet(
imageUrl:
'https://d18x2uyjeekruj.cloudfront.net/wp-content/uploads/2019/04/Scan12.jpg',
downloadedImagePath: '',
selectedOffsets: List()),
AnswerSheet(
imageUrl:
'https://d18x2uyjeekruj.cloudfront.net/wp-content/uploads/2019/04/Scan12.jpg',
downloadedImagePath: '',
selectedOffsets: List())
];
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomInset: false,
body: GestureDetector(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) =>
EntryItem(answerSheets[index]),
itemCount: answerSheets.length,
),
));
}
}
class EntryItem extends StatefulWidget {
final AnswerSheet answerSheet;
EntryItem(this.answerSheet);
#override
_EntryItemState createState() => _EntryItemState();
}
class _EntryItemState extends State<EntryItem> {
final GlobalKey _myCanvasKey = new GlobalKey();
MyCustomPainter _customPainter;
Offset _startOffset;
bool isLoading = true;
ui.Image _image;
bool _isImageEditable = true;
BuildContext context;
#override
void initState() {
super.initState();
_downloadImage();
}
#override
Widget build(BuildContext context) {
this.context = context;
if (isLoading) {
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Center(child: CircularProgressIndicator()));
} else {
return GestureDetector(
onHorizontalDragStart: _onHorizontalDragStart,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onHorizontalDragEnd: _onHorizontalDragEnd,
child: Container(
margin: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
color: Color(0xFFF4F4F4),
borderRadius: BorderRadius.circular(10.0)),
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: CustomPaint(
key: _myCanvasKey,
size: MediaQuery.of(context).size,
painter: _customPainter,
),
),
));
}
}
Future downloadAndSaveImage(AnswerSheet answerSheet) async {
print("downloading....");
var response = await get(answerSheet.imageUrl);
var documentDirectory = await getApplicationDocumentsDirectory();
File file = File(join(documentDirectory.path, '${DateTime.now()}.jpg'));
file.writeAsBytesSync(response.bodyBytes);
answerSheet.downloadedImagePath = file.path;
print(file.path);
return response.bodyBytes;
}
Future<Null> _downloadImage() async {
List<int> img = await downloadAndSaveImage(widget.answerSheet);
_image = await _loadImage(img);
setState(() {
_customPainter =
MyCustomPainter(answerSheet: widget.answerSheet, image: _image);
isLoading = false;
});
}
Future<ui.Image> _loadImage(List<int> img) async {
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(img, (ui.Image img) {
return completer.complete(img);
});
return completer.future;
}
Rect getRect(Offset offset) {
return Rect.fromPoints(offset, Offset(offset.dx + 30, offset.dy + 30));
}
_onHorizontalDragStart(DragStartDetails detailData) {
if (_isImageEditable) {
_startOffset = detailData.globalPosition;
widget.answerSheet.selectedOffsets.add(_startOffset);
}
}
_onHorizontalDragUpdate(DragUpdateDetails detailData) {
if (_isImageEditable) {
widget.answerSheet.selectedOffsets
.add(Offset(detailData.localPosition.dx, _startOffset.dy));
_myCanvasKey.currentContext.findRenderObject().markNeedsPaint();
}
}
_onHorizontalDragEnd(DragEndDetails details) {
print('_onHorizontalDragEnd');
if (_isImageEditable) {
_myCanvasKey.currentContext.findRenderObject().markNeedsPaint();
_startOffset = null;
}
}
}
class MyCustomPainter extends CustomPainter {
final AnswerSheet answerSheet;
final ui.Image image;
MyCustomPainter({this.answerSheet, this.image});
Paint _paint = new Paint()
..color = Colors.deepOrange.withOpacity(0.3)
..style = PaintingStyle.stroke;
Offset _prvOffset;
#override
void paint(Canvas canvas, Size size) {
_paint.strokeWidth = 40;
Rect myRect = Offset(0.0, 0.0) & Size(size.width, size.height);
drawImage(myRect, size, canvas, new Paint(), BoxFit.fill);
if (answerSheet.selectedOffsets.length != 0) {
for (Offset currOffset in answerSheet.selectedOffsets) {
if (_prvOffset != null && currOffset != null)
canvas.drawLine(_prvOffset, currOffset, _paint);
_prvOffset = currOffset;
}
_prvOffset = null;
}
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
Paint getPaint(Color color) {
return new Paint()
..isAntiAlias = true
..strokeWidth = 1.0
..color = color
..style = PaintingStyle.fill;
}
void drawImage(
Rect outputRect, Size size, Canvas canvas, Paint paint, BoxFit fit) {
final Size imageSize =
Size(image.width.toDouble(), image.height.toDouble());
final FittedSizes sizes = applyBoxFit(fit, imageSize, outputRect.size);
final Rect inputSubrect =
Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
final Rect outputSubrect =
Alignment.center.inscribe(sizes.destination, outputRect);
canvas.drawImageRect(image, inputSubrect, outputSubrect, paint);
}
}
class AnswerSheet {
String imageUrl;
String downloadedImagePath;
List<Offset> selectedOffsets;
AnswerSheet({this.imageUrl, this.downloadedImagePath, this.selectedOffsets});
}
screenshot
A simple plugin to capture widgets as Images.
This plugin wraps your widgets inside RenderRepaintBoundary
This handy plugin can be used to capture any Widget including full screen screenshots & individual widgets like Text().
Ok, you need to use image_cropper or crop packages. These are helpful to you. Look at the below example:
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ImageCropper',
theme: ThemeData.light().copyWith(primaryColor: Colors.deepOrange),
home: MyHomePage(
title: 'ImageCropper',
),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({this.title});
#override
_MyHomePageState createState() => _MyHomePageState();
}
enum AppState {
free,
picked,
cropped,
}
class _MyHomePageState extends State<MyHomePage> {
AppState state;
File imageFile;
#override
void initState() {
super.initState();
state = AppState.free;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: imageFile != null ? Image.file(imageFile) : Container(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.deepOrange,
onPressed: () {
if (state == AppState.free)
_pickImage();
else if (state == AppState.picked)
_cropImage();
else if (state == AppState.cropped) _clearImage();
},
child: _buildButtonIcon(),
),
);
}
Widget _buildButtonIcon() {
if (state == AppState.free)
return Icon(Icons.add);
else if (state == AppState.picked)
return Icon(Icons.crop);
else if (state == AppState.cropped)
return Icon(Icons.clear);
else
return Container();
}
Future<Null> _pickImage() async {
imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
if (imageFile != null) {
setState(() {
state = AppState.picked;
});
}
}
Future<Null> _cropImage() async {
File croppedFile = await ImageCropper.cropImage(
sourcePath: imageFile.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
]
: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio5x3,
CropAspectRatioPreset.ratio5x4,
CropAspectRatioPreset.ratio7x5,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Cropper',
));
if (croppedFile != null) {
imageFile = croppedFile;
setState(() {
state = AppState.cropped;
});
}
}
void _clearImage() {
imageFile = null;
setState(() {
state = AppState.free;
});
}
}

How to crop Image from image picker in flutter?

I want to allow the user to crop the Image he chose from the image picker and save it(Similar to uploading profile pic on Whatsapp). How can I do this in flutter?
Sample Image:
You can use these 2 flutter libraries to achieve this,
image_picker;
image_cropper
The image picker use the native libraries in iOS and Android to achieve it, therefore it will delivery a good performance way.
Here is a sample available in image_picker:
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
void main() => runApp(new ConfigScreen());
class ConfigScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ImageCropper',
theme: ThemeData.light().copyWith(primaryColor: Colors.deepOrange),
home: MyHomePage(
title: 'ImageCropper',
),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({this.title});
#override
_MyHomePageState createState() => _MyHomePageState();
}
enum AppState {
free,
picked,
cropped,
}
class _MyHomePageState extends State<MyHomePage> {
AppState state;
File imageFile;
#override
void initState() {
super.initState();
state = AppState.free;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: imageFile != null ? Image.file(imageFile) : Container(),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.deepOrange,
onPressed: () {
if (state == AppState.free)
_pickImage();
else if (state == AppState.picked)
_cropImage();
else if (state == AppState.cropped) _clearImage();
},
child: _buildButtonIcon(),
),
);
}
Widget _buildButtonIcon() {
if (state == AppState.free)
return Icon(Icons.add);
else if (state == AppState.picked)
return Icon(Icons.crop);
else if (state == AppState.cropped)
return Icon(Icons.clear);
else
return Container();
}
Future<Null> _pickImage() async {
imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
if (imageFile != null) {
setState(() {
state = AppState.picked;
});
}
}
Future<Null> _cropImage() async {
File croppedFile = await ImageCropper.cropImage(
sourcePath: imageFile.path,
aspectRatioPresets: Platform.isAndroid
? [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
]
: [
CropAspectRatioPreset.original,
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio5x3,
CropAspectRatioPreset.ratio5x4,
CropAspectRatioPreset.ratio7x5,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
title: 'Cropper',
));
if (croppedFile != null) {
imageFile = croppedFile;
setState(() {
state = AppState.cropped;
});
}
}
void _clearImage() {
imageFile = null;
setState(() {
state = AppState.free;
});
}
}
The image_picker already can crop the image. You pass in the specified width and height for the image you want and the plugin actually crops the original image.
_imageFile = ImagePicker.pickImage(source: source, maxWidth: 200.0, maxHeight: 300.0);
What you are asking for is another plugin to crop images after one has been selected and that would be outside the scope of the image_picker.
I am facing something similar and you can always have the user edit the photo or video with the built in camera app until there is a plugin made for cropping images.
For cropping images on the UI level you can do something like this:
https://stackoverflow.com/a/44665742/7303311
To crop the image from image_cropper library you case just set the
aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1)
Here's the sample code:
CroppedFile? croppedFile = await ImageCropper().cropImage(
sourcePath: pickedImage.path,
aspectRatio: imagePickingType == ImagePickingType.profilePic ? CropAspectRatio(ratioX: 1, ratioY: 1) :
imagePickingType == ImagePickingType.communityWall ? CropAspectRatio(ratioX: 16, ratioY: 9) : null,
uiSettings: [
AndroidUiSettings(
toolbarTitle: cropPageTitle ?? 'Edit Image',
toolbarColor: toolbarTextColor ??
theme.scaffoldBackgroundColor,
toolbarWidgetColor: toolbarBackgroundColor ??
theme.primaryColor,
initAspectRatio:
initialAspectRation ?? CropAspectRatioPreset.original,
lockAspectRatio: (imagePickingType == ImagePickingType.profilePic) || (imagePickingType == ImagePickingType.communityWall),
backgroundColor: theme.scaffoldBackgroundColor,
activeControlsWidgetColor: theme.primaryColor,
),
IOSUiSettings(
title: cropPageTitle ?? 'Edit Image',
rotateClockwiseButtonHidden: true,
aspectRatioPickerButtonHidden: true,
aspectRatioLockEnabled: (imagePickingType == ImagePickingType.profilePic) || (imagePickingType == ImagePickingType.communityWall),
rotateButtonsHidden: true,
),
],
);
if (croppedFile != null) {
return File(croppedFile.path);
} else {
File(pickedImage.path);
}