Skip to content

Commit 63bee12

Browse files
Merge pull request #185 from NativeScript/msaravitz/add-allows-editing-ios
feat: allow editing on iOS
2 parents 112fcdd + bd261bc commit 63bee12

File tree

8 files changed

+44
-12
lines changed

8 files changed

+44
-12
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ npm install nativescript-camera --save
4040
| isAvailable() | Is the device camera available to use. |
4141

4242
### CameraOptions
43-
| Property | Default | Description |
44-
| --- | --- | --- |
45-
| width | 0 | Defines the desired width (in device independent pixels) of the taken image. It should be used with height property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image width will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
46-
| height | 0 | Defines the desired height (in device independent pixels) of the taken image. It should be used with width property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image height will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
47-
| keepAspectRatio | true | Defines if camera picture aspect ratio should be kept during picture resizing. This property could affect width or height return values. |
48-
| saveToGallery | true | Defines if camera picture should be copied to photo Gallery (Android) or Photos (iOS) |
49-
| cameraFacing | rear | The initial camera facing. Use 'front' for selfies. |
43+
| Property | Default | Platform | Description |
44+
| --- | --- | --- | --- |
45+
| width | 0 | Both | Defines the desired width (in device independent pixels) of the taken image. It should be used with height property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image width will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
46+
| height | 0 | Both | Defines the desired height (in device independent pixels) of the taken image. It should be used with width property. If `keepAspectRatio` actual image width could be different in order to keep the aspect ratio of the original camera image. The actual image height will be greater than requested if the display density of the device is higher (than 1) (full HD+ resolutions). |
47+
| keepAspectRatio | true | Both | Defines if camera picture aspect ratio should be kept during picture resizing. This property could affect width or height return values. |
48+
| saveToGallery | true | Both | Defines if camera picture should be copied to photo Gallery (Android) or Photos (iOS) |
49+
| allowsEditing | false | iOS | Defines if camera "Retake" or "Use Photo" screen forces the user to crop camera picture to a square and optionally lets them zoom in. |
50+
| cameraFacing | rear | Both | The initial camera facing. Use 'front' for selfies. |
5051

5152

5253
> Note: The `saveToGallery` option might have unexpected behavior on Android! Some vendor camera apps (e.g. LG) will save all captured images to the gallery regardless of what the value of `saveToGallery` is. This behavior cannot be controlled by the camera plugin and if you must exclude the captured image from the photo gallery, you will need to get a local storage read/write permission and write custom code to find the gallery location and delete the new image from there.
@@ -131,6 +132,7 @@ __Example 2__ shows how to take a picture using the NativeScript camera module.
131132
* __height__: The desired height of the picture (in device independent pixels).
132133
* __keepAspectRatio__: A boolean parameter that indicates if the aspect ratio should be kept.
133134
* __saveToGallery__: A boolean parameter that indicates if the original taken photo will be saved in "Photos" for Android and in "Camera Roll" in iOS
135+
* __allowsEditing__: (iOS Only) A boolean parameter that indicates if the camera "Retake" or "Use Photo" screen forces the user to crop camera picture to a square and optionally lets them zoom in.
134136
* __cameraFacing__: Start with either the "front" or "rear" (default) camera of the device. The current implementation doesn't work on all Android devices, in which case it falls back to the default behavior.
135137

136138
What does `device independent pixels` mean? The NativeScript layout mechanism uses device-independent pixels when measuring UI controls. This allows you to declare one layout and this layout will look similar to all devices (no matter the device's display resolution). In order to get a proper image quality for high resolution devices (like iPhone retina and Android Full HD), camera will return an image with bigger dimensions. For example, if we request an image that is 100x100, on iPhone 6 the actual image will be 200x200 (since its display density factor is 2 -> 100*2x100*2).

demo-angular/app/app.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<Label text="saveToGallery"></Label>
66
<Switch [(ngModel)]="saveToGallery"></Switch>
77
</StackLayout>
8+
<StackLayout android:visibility="collapsed" orientation="horizontal" padding="10">
9+
<Label text="allowsEditing"></Label>
10+
<Switch [(ngModel)]="allowsEditing"></Switch>
11+
</StackLayout>
812
<StackLayout orientation="horizontal" padding="10">
913
<Label text="keepAspectRatio"></Label>
1014
<Switch [(ngModel)]="keepAspectRatio"></Switch>

demo-angular/app/app.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ImageAsset } from 'tns-core-modules/image-asset';
88
})
99
export class AppComponent {
1010
public saveToGallery: boolean = false;
11+
public allowsEditing: boolean = false;
1112
public keepAspectRatio: boolean = true;
1213
public width: number = 320;
1314
public height: number = 240;
@@ -20,7 +21,7 @@ export class AppComponent {
2021
onTakePictureTap(args) {
2122
requestPermissions().then(
2223
() => {
23-
takePicture({ width: this.width, height: this.height, keepAspectRatio: this.keepAspectRatio, saveToGallery: this.saveToGallery })
24+
takePicture({ width: this.width, height: this.height, keepAspectRatio: this.keepAspectRatio, saveToGallery: this.saveToGallery, allowsEditing: this.allowsEditing })
2425
.then((imageAsset: any) => {
2526
this.cameraImage = imageAsset;
2627
let that = this;

demo-vue/app/components/Home.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
<Label text="saveToGallery" />
1111
<Switch v-model="saveToGallery"/>
1212
</StackLayout>
13+
<StackLayout android:visibility="collapsed" orientation="horizontal" row="0" padding="5">
14+
<Label text="allowsEditing" />
15+
<Switch v-model="allowsEditing"/>
16+
</StackLayout>
1317
<StackLayout orientation="horizontal" row="0" padding="5">
1418
<Label text="keepAspectRatio" />
1519
<Switch v-model="keepAspectRatio"/>
@@ -37,6 +41,7 @@
3741
data() {
3842
return {
3943
saveToGallery: false,
44+
allowsEditing: false,
4045
keepAspectRatio: true,
4146
width: 320,
4247
height: 240,
@@ -50,7 +55,7 @@
5055
let that = this;
5156
requestPermissions().then(
5257
() => {
53-
takePicture({ width: that.width, height: that.height, keepAspectRatio: that.keepAspectRatio, saveToGallery: that.saveToGallery }).
58+
takePicture({ width: that.width, height: that.height, keepAspectRatio: that.keepAspectRatio, saveToGallery: that.saveToGallery, allowsEditing: that.allowsEditing }).
5459
then((imageAsset) => {
5560
that.cameraImage = imageAsset;
5661
imageAsset.getImageAsync(function (nativeImage) {

demo/app/main-page.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export function navigatingTo(args: EventData) {
1414
page.bindingContext = fromObject({
1515
cameraImage: picturePath,
1616
saveToGallery: false,
17+
allowsEditing: false,
1718
keepAspectRatio: true,
1819
width: 320,
1920
height: 240
@@ -23,12 +24,13 @@ export function navigatingTo(args: EventData) {
2324
export function onTakePictureTap(args: EventData) {
2425
let page = <Page>(<View>args.object).page;
2526
let saveToGallery = page.bindingContext.get("saveToGallery");
27+
let allowsEditing = page.bindingContext.get("allowsEditing");
2628
let keepAspectRatio = page.bindingContext.get("keepAspectRatio");
2729
let width = page.bindingContext.get("width");
2830
let height = page.bindingContext.get("height");
2931
requestPermissions().then(
3032
() => {
31-
takePicture({ width: width, height: height, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery }).
33+
takePicture({ width: width, height: height, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery, allowsEditing: allowsEditing }).
3234
then((imageAsset) => {
3335
page.bindingContext.set("cameraImage", imageAsset);
3436
imageAsset.getImageAsync(function (nativeImage) {

demo/app/main-page.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
<Label text="saveToGallery" />
77
<Switch checked="{{ saveToGallery }}"/>
88
</StackLayout>
9+
<StackLayout android:visibility="collapsed" orientation="horizontal" row="0" padding="5">
10+
<Label text="allowsEditing" />
11+
<Switch checked="{{ allowsEditing }}"/>
12+
</StackLayout>
913
<StackLayout orientation="horizontal" row="0" padding="5">
1014
<Label text="keepAspectRatio" />
1115
<Switch checked="{{ keepAspectRatio }}"/>

src/camera.ios.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
1818
private _height: number;
1919
private _keepAspectRatio: boolean;
2020
private _saveToGallery: boolean;
21+
private _allowsEditing: boolean;
2122

2223
public initWithCallback(callback: (result?) => void, errorCallback: (result?) => void): UIImagePickerControllerDelegateImpl {
2324
this._callback = callback;
@@ -32,6 +33,7 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
3233
this._width = options.width;
3334
this._height = options.height;
3435
this._saveToGallery = options.saveToGallery;
36+
this._allowsEditing = options.allowsEditing;
3537
this._keepAspectRatio = types.isNullOrUndefined(options.keepAspectRatio) ? true : options.keepAspectRatio;
3638
}
3739
return this;
@@ -41,6 +43,9 @@ class UIImagePickerControllerDelegateImpl extends NSObject implements UIImagePic
4143
if (info) {
4244
let currentDate: Date = new Date();
4345
let source = info.valueForKey(UIImagePickerControllerOriginalImage);
46+
if (this._allowsEditing) {
47+
source = info.valueForKey(UIImagePickerControllerEditedImage);
48+
}
4449
if (source) {
4550
let imageSource: typeof imageSourceModule = require("image-source");
4651
let imageSourceResult = imageSource.fromNativeSource(source);
@@ -129,11 +134,13 @@ export let takePicture = function (options): Promise<any> {
129134
let reqHeight = 0;
130135
let keepAspectRatio = true;
131136
let saveToGallery = true;
137+
let allowsEditing = false;
132138
if (options) {
133139
reqWidth = options.width || 0;
134140
reqHeight = options.height || reqWidth;
135141
keepAspectRatio = types.isNullOrUndefined(options.keepAspectRatio) ? keepAspectRatio : options.keepAspectRatio;
136142
saveToGallery = types.isNullOrUndefined(options.saveToGallery) ? saveToGallery : options.saveToGallery;
143+
allowsEditing = types.isNullOrUndefined(options.allowsEditing) ? allowsEditing : options.allowsEditing;
137144
}
138145

139146
let authStatus = PHPhotoLibrary.authorizationStatus();
@@ -143,10 +150,10 @@ export let takePicture = function (options): Promise<any> {
143150

144151
if (reqWidth && reqHeight) {
145152
listener = UIImagePickerControllerDelegateImpl.new().initWithCallbackAndOptions(
146-
resolve, reject, { width: reqWidth, height: reqHeight, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery });
153+
resolve, reject, { width: reqWidth, height: reqHeight, keepAspectRatio: keepAspectRatio, saveToGallery: saveToGallery, allowsEditing: allowsEditing });
147154
} else if (saveToGallery) {
148155
listener = UIImagePickerControllerDelegateImpl.new().initWithCallbackAndOptions(
149-
resolve, reject, { saveToGallery: saveToGallery, keepAspectRatio: keepAspectRatio });
156+
resolve, reject, { saveToGallery: saveToGallery, keepAspectRatio: keepAspectRatio, allowsEditing: allowsEditing });
150157
} else {
151158
listener = UIImagePickerControllerDelegateImpl.new().initWithCallback(resolve, reject);
152159
}
@@ -162,6 +169,7 @@ export let takePicture = function (options): Promise<any> {
162169
imagePickerController.sourceType = sourceType;
163170
imagePickerController.cameraDevice = options && options.cameraFacing === "front" ?
164171
UIImagePickerControllerCameraDevice.Front : UIImagePickerControllerCameraDevice.Rear;
172+
imagePickerController.allowsEditing = allowsEditing;
165173
}
166174

167175
imagePickerController.modalPresentationStyle = UIModalPresentationStyle.CurrentContext;

src/index.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ export interface CameraOptions {
4444
*/
4545
saveToGallery?: boolean;
4646

47+
/**
48+
* iOS Only
49+
* Defines if camera "Retake" or "Use Photo" screen forces user to crop camera picture to a square and optionally lets them zoom in.
50+
*/
51+
allowsEditing?: boolean;
52+
4753
/**
4854
* The initial camera. Default "rear".
4955
* The current implementation doesn't work on all Android devices, in which case it falls back to the default behavior.

0 commit comments

Comments
 (0)