@@ -38,27 +38,27 @@ class CustomImageCrop extends StatefulWidget {
3838 /// `DottedCropPathPainter.drawPath` and
3939 /// `SolidCropPathPainter.drawPath`
4040 const CustomImageCrop ({
41- @required this .image,
42- @required this .cropController,
43- Key key,
41+ required this .image,
42+ required this .cropController,
4443 this .overlayColor = const Color .fromRGBO (0 , 0 , 0 , 0.5 ),
4544 this .backgroundColor = Colors .white,
4645 this .shape = CustomCropShape .Circle ,
4746 this .cropPercentage = 0.8 ,
4847 this .drawPath = DottedCropPathPainter .drawPath,
48+ Key ? key,
4949 }) : super (key: key);
5050
5151 @override
5252 _CustomImageCropState createState () => _CustomImageCropState ();
5353}
5454
5555class _CustomImageCropState extends State <CustomImageCrop > with CustomImageCropListener {
56- CropImageData dataTransitionStart;
57- Path path;
58- double width, height;
59- ui.Image imageAsUIImage;
60- ImageStream _imageStream;
61- ImageStreamListener _imageListener;
56+ CropImageData ? dataTransitionStart;
57+ late Path path;
58+ late double width, height;
59+ ui.Image ? imageAsUIImage;
60+ ImageStream ? _imageStream;
61+ ImageStreamListener ? _imageListener;
6262
6363 @override
6464 void initState () {
@@ -75,10 +75,12 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
7575 void _getImage () {
7676 final oldImageStream = _imageStream;
7777 _imageStream = widget.image.resolve (createLocalImageConfiguration (context));
78- if (_imageStream.key != oldImageStream? .key) {
79- oldImageStream? .removeListener (_imageListener);
78+ if (_imageStream? .key != oldImageStream? .key) {
79+ if (_imageListener != null ) {
80+ oldImageStream? .removeListener (_imageListener! );
81+ }
8082 _imageListener = ImageStreamListener (_updateImage);
81- _imageStream.addListener (_imageListener);
83+ _imageStream? .addListener (_imageListener! );
8284 }
8385 }
8486
@@ -90,22 +92,25 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
9092
9193 @override
9294 void dispose () {
93- _imageStream? .removeListener (_imageListener);
95+ if (_imageListener != null ) {
96+ _imageStream? .removeListener (_imageListener! );
97+ }
9498 widget.cropController.removeListener (this );
9599 super .dispose ();
96100 }
97101
98102 @override
99103 Widget build (BuildContext context) {
100- if (imageAsUIImage == null ) {
104+ final image = imageAsUIImage;
105+ if (image == null ) {
101106 return const Center (child: CircularProgressIndicator ());
102107 }
103108 return LayoutBuilder (
104109 builder: (context, constraints) {
105110 width = constraints.maxWidth;
106111 height = constraints.maxHeight;
107112 final cropWidth = min (width, height) * widget.cropPercentage;
108- final defaultScale = min (imageAsUIImage .width, imageAsUIImage .height) / cropWidth;
113+ final defaultScale = min (image .width, image .height) / cropWidth;
109114 final scale = data.scale * defaultScale;
110115 path = _getPath (cropWidth, width, height);
111116 return XGestureDetector (
@@ -125,7 +130,7 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
125130 child: Transform (
126131 transform: Matrix4 .diagonal3 (vector_math.Vector3 (scale, scale, 0 ))
127132 ..rotateZ (data.angle)
128- ..translate (- imageAsUIImage .width / 2 , - imageAsUIImage .height / 2 ),
133+ ..translate (- image .width / 2 , - image .height / 2 ),
129134 child: Image (
130135 image: widget.image,
131136 ),
@@ -139,9 +144,7 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
139144 ),
140145 ),
141146 ),
142- if (widget.drawPath != null ) ...{
143- widget.drawPath (path),
144- },
147+ widget.drawPath (path),
145148 ],
146149 ),
147150 ),
@@ -156,7 +159,7 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
156159
157160 void onScaleUpdate (ScaleEvent event) {
158161 if (dataTransitionStart != null ) {
159- addTransition (dataTransitionStart - CropImageData (scale: event.scale, angle: event.rotationAngle));
162+ addTransition (dataTransitionStart! - CropImageData (scale: event.scale, angle: event.rotationAngle));
160163 }
161164 dataTransitionStart = CropImageData (scale: event.scale, angle: event.rotationAngle);
162165 }
@@ -192,14 +195,14 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
192195 }
193196
194197 @override
195- Future <MemoryImage > onCropImage () async {
198+ Future <MemoryImage ? > onCropImage () async {
196199 if (imageAsUIImage == null ) {
197200 return null ;
198201 }
199202 final cropWidth = min (width, height) * widget.cropPercentage;
200203 final pictureRecorder = ui.PictureRecorder ();
201204 final canvas = Canvas (pictureRecorder);
202- final defaultScale = min (imageAsUIImage.width, imageAsUIImage.height) / cropWidth;
205+ final defaultScale = min (imageAsUIImage! .width, imageAsUIImage! .height) / cropWidth;
203206 final scale = data.scale * defaultScale;
204207 final clipPath = Path .from (_getPath (cropWidth, cropWidth, cropWidth));
205208 final matrix4Image = Matrix4 .diagonal3 (vector_math.Vector3 (1 , 1 , 0 ))
@@ -214,7 +217,7 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
214217 canvas.save ();
215218 canvas.clipPath (clipPath);
216219 canvas.transform (matrix4Image.storage);
217- canvas.drawImage (imageAsUIImage, Offset (- imageAsUIImage.width / 2 , - imageAsUIImage.height / 2 ), imagePaint);
220+ canvas.drawImage (imageAsUIImage! , Offset (- imageAsUIImage! .width / 2 , - imageAsUIImage! .height / 2 ), imagePaint);
218221 canvas.restore ();
219222
220223 // Optionally remove magenta from image by evaluating every pixel
@@ -228,7 +231,7 @@ class _CustomImageCropState extends State<CustomImageCrop> with CustomImageCropL
228231 // A workaround would be to save the image and load it inside of the isolate
229232 final bytes = await image.toByteData (format: ui.ImageByteFormat .png);
230233
231- return MemoryImage (bytes.buffer.asUint8List ());
234+ return bytes == null ? null : MemoryImage (bytes.buffer.asUint8List ());
232235 }
233236
234237 @override
0 commit comments