frank frank - 1 year ago 259
iOS Question

UIImagePickerController overlay view using React Native components

I want to define a

UIImagePickerController
overlay view using React Native components. I'm setting up to add a new option to Marc Shilling fabulous react-native-image-picker. I want the
ImagePickerManager.launchCamera
function to take a
<View>
and children as one of its parameters, render it, and pass that to
UIImagePickerController.cameraOverlayView
. I got this far:

In ImagePickerManager.m:

NSNumber *viewTag = [self.options valueForKey:@"overlayNode"];
if (![viewTag isEqual:[NSNull null]] && viewTag != 0) {
UIView *view = [_bridge.uiManager viewForReactTag:viewTag];
[self.picker setCameraOverlayView:view];
}


But this requires me to do some contortions on the JS side in order to get a component instance.

React.createClass({
render: function() {
return (
<View>
<TouchableHighlight onPress={this._showCamera}><Text>Camera</Text></TouchableHighlight>
<View ref="foo"><Text>On top of the camera!</Text></View>
</View>
);
},
_showCamera: function() {
var options = {
overlayNode: React.findNodeHandle(this.refs.foo),
};
ImagePickerManager.launchCamera(options, (response) => {

});
}
});


I get a redbox if I try to say
overlayNode: React.findNodeHandle(<View ref="foo"><Text>On top of the camera!</Text></View>)
.

I experimented a bit with creating a new
RCTRootView
and registering the overlay via
AppRegistry.registerComponent
but I didn't see anything actually render on the screen.

NSString *overlayRootName = [self.options valueForKey:@"overlayComponentName"];
if (![overlayRootName isEqual:[NSNull null]] && overlayRootName.length != 0) {
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:self.bridge moduleName:overlayRootName initialProperties:nil];
[self.picker setCameraOverlayView:rootView];
}


What am I missing here?

Answer Source

The latter solution (declaring an alternative RCTRootView) ended up being the one that worked for me. The problem I was having was that for some reason the bridge that I got in the ImagePickerManager from adding @synthesize bridge = _bridge; was not rendering anything when used in initWithBridge.

Instead, I added a field to my AppDelegate exposing the bridge created in application: didFinishLaunchingWithOptions: much like what was done in this hybrid app example. When I use that bridge in initWithBridge, the overlay renders on the screen. Also made sure to explicitly set rootView.frame and rootView.backgroundColor to transparent.

Screenshot of UIImagePicker with React Native Overlay

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download