Skip to content

Commit f3bb044

Browse files
Chris Yangamirh
authored andcommitted
[Image_picker] fix rotation regression on Android. (flutter#2362)
1 parent 94b6321 commit f3bb044

4 files changed

Lines changed: 98 additions & 21 deletions

File tree

packages/image_picker/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
## 0.6.2+2
1+
## 0.6.2+3
22

33
* Remove the deprecated `author:` field from pubspec.yaml
44
* Migrate the plugin to the pubspec platforms manifest.
55
* Require Flutter SDK 1.10.0 or greater.
66

7+
## 0.6.2+2
8+
* Android: Revert the image file return logic when the image doesn't have to be scaled. Fix a rotation regression caused by 0.6.2+1
9+
* Example App: Add a dialog to enter `maxWidth`, `maxHeight` or `quality` when picking image.
10+
711
## 0.6.2+1
812

913
* Android: Fix a crash when a non-image file is picked.

packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,19 @@ String resizeImageIfNeeded(
3333
@Nullable Double maxWidth,
3434
@Nullable Double maxHeight,
3535
@Nullable Integer imageQuality) {
36-
boolean shouldScale =
37-
maxWidth != null || maxHeight != null || isImageQualityValid(imageQuality);
38-
String[] pathParts = imagePath.split("/");
39-
String imageName = pathParts[pathParts.length - 1];
40-
File file;
4136
Bitmap bmp = decodeFile(imagePath);
4237
if (bmp == null) {
4338
return null;
4439
}
40+
boolean shouldScale =
41+
maxWidth != null || maxHeight != null || isImageQualityValid(imageQuality);
42+
if (!shouldScale) {
43+
return imagePath;
44+
}
4545
try {
46-
if (!shouldScale) {
47-
file = createImageOnExternalDirectory(imageName, bmp, 100);
48-
} else {
49-
file = resizedImage(bmp, maxWidth, maxHeight, imageQuality, imageName);
50-
}
46+
String[] pathParts = imagePath.split("/");
47+
String imageName = pathParts[pathParts.length - 1];
48+
File file = resizedImage(bmp, maxWidth, maxHeight, imageQuality, imageName);
5149
copyExif(imagePath, file.getPath());
5250
return file.getPath();
5351
} catch (IOException e) {

packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void setUp() throws IOException {
4242
@Test
4343
public void onResizeImageIfNeeded_WhenQualityIsNull_ShoultNotResize_ReturnTheUnscaledFile() {
4444
String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, null);
45-
assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/pngImage.png"));
45+
assertThat(outoutFile, equalTo(imageFile.getPath()));
4646
}
4747

4848
@Test

packages/image_picker/example/lib/main.dart

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import 'dart:async';
88
import 'dart:io';
99

1010
import 'package:flutter/material.dart';
11+
import 'package:flutter/src/widgets/basic.dart';
12+
import 'package:flutter/src/widgets/container.dart';
1113
import 'package:image_picker/image_picker.dart';
1214
import 'package:video_player/video_player.dart';
1315

@@ -41,6 +43,10 @@ class _MyHomePageState extends State<MyHomePage> {
4143
VideoPlayerController _controller;
4244
String _retrieveDataError;
4345

46+
final TextEditingController maxWidthController = TextEditingController();
47+
final TextEditingController maxHeightController = TextEditingController();
48+
final TextEditingController qualityController = TextEditingController();
49+
4450
Future<void> _playVideo(File file) async {
4551
if (file != null && mounted) {
4652
await _disposeVideoController();
@@ -53,20 +59,27 @@ class _MyHomePageState extends State<MyHomePage> {
5359
}
5460
}
5561

56-
void _onImageButtonPressed(ImageSource source) async {
62+
void _onImageButtonPressed(ImageSource source, {BuildContext context}) async {
5763
if (_controller != null) {
5864
await _controller.setVolume(0.0);
5965
}
6066
if (isVideo) {
6167
final File file = await ImagePicker.pickVideo(source: source);
6268
await _playVideo(file);
6369
} else {
64-
try {
65-
_imageFile = await ImagePicker.pickImage(source: source);
66-
setState(() {});
67-
} catch (e) {
68-
_pickImageError = e;
69-
}
70+
await _displayPickImageDialog(context,
71+
(double maxWidth, double maxHeight, int quality) async {
72+
try {
73+
_imageFile = await ImagePicker.pickImage(
74+
source: source,
75+
maxWidth: maxWidth,
76+
maxHeight: maxHeight,
77+
imageQuality: quality);
78+
setState(() {});
79+
} catch (e) {
80+
_pickImageError = e;
81+
}
82+
});
7083
}
7184
}
7285

@@ -82,6 +95,9 @@ class _MyHomePageState extends State<MyHomePage> {
8295
@override
8396
void dispose() {
8497
_disposeVideoController();
98+
maxWidthController.dispose();
99+
maxHeightController.dispose();
100+
qualityController.dispose();
85101
super.dispose();
86102
}
87103

@@ -192,7 +208,7 @@ class _MyHomePageState extends State<MyHomePage> {
192208
FloatingActionButton(
193209
onPressed: () {
194210
isVideo = false;
195-
_onImageButtonPressed(ImageSource.gallery);
211+
_onImageButtonPressed(ImageSource.gallery, context: context);
196212
},
197213
heroTag: 'image0',
198214
tooltip: 'Pick Image from gallery',
@@ -203,7 +219,7 @@ class _MyHomePageState extends State<MyHomePage> {
203219
child: FloatingActionButton(
204220
onPressed: () {
205221
isVideo = false;
206-
_onImageButtonPressed(ImageSource.camera);
222+
_onImageButtonPressed(ImageSource.camera, context: context);
207223
},
208224
heroTag: 'image1',
209225
tooltip: 'Take a Photo',
@@ -249,8 +265,67 @@ class _MyHomePageState extends State<MyHomePage> {
249265
}
250266
return null;
251267
}
268+
269+
Future<void> _displayPickImageDialog(
270+
BuildContext context, OnPickImageCallback onPick) async {
271+
return showDialog(
272+
context: context,
273+
builder: (context) {
274+
return AlertDialog(
275+
title: Text('Add optional parameters'),
276+
content: Column(
277+
children: <Widget>[
278+
TextField(
279+
controller: maxWidthController,
280+
keyboardType: TextInputType.numberWithOptions(decimal: true),
281+
decoration:
282+
InputDecoration(hintText: "Enter maxWidth if desired"),
283+
),
284+
TextField(
285+
controller: maxHeightController,
286+
keyboardType: TextInputType.numberWithOptions(decimal: true),
287+
decoration:
288+
InputDecoration(hintText: "Enter maxHeight if desired"),
289+
),
290+
TextField(
291+
controller: qualityController,
292+
keyboardType: TextInputType.number,
293+
decoration:
294+
InputDecoration(hintText: "Enter quality if desired"),
295+
),
296+
],
297+
),
298+
actions: <Widget>[
299+
FlatButton(
300+
child: const Text('CANCEL'),
301+
onPressed: () {
302+
Navigator.of(context).pop();
303+
},
304+
),
305+
FlatButton(
306+
child: const Text('PICK'),
307+
onPressed: () {
308+
double width = maxWidthController.text.length > 0
309+
? double.parse(maxWidthController.text)
310+
: null;
311+
double height = maxHeightController.text.length > 0
312+
? double.parse(maxHeightController.text)
313+
: null;
314+
int quality = qualityController.text.length > 0
315+
? int.parse(qualityController.text)
316+
: null;
317+
onPick(width, height, quality);
318+
Navigator.of(context).pop();
319+
}),
320+
],
321+
);
322+
});
323+
}
252324
}
253325

326+
typedef void OnPickImageCallback(
327+
double maxWidth, double maxHeight, int quality);
328+
254329
class AspectRatioVideo extends StatefulWidget {
255330
AspectRatioVideo(this.controller);
256331

0 commit comments

Comments
 (0)