How Can I Open a Camera From Within my React Native App? - react-native

I'm working on an app where we want to allow our users (tech support personnel) to take a photo of an employee's badge so we can analyze the photo and extract the badge ID (we already have an open source algorithm to do this) to create a ticket. I have the app running a webview of the application used by helpdesk personnel from their desktops, as well as a button at the top to open the camera (currently it's just an alert). Code is below:
const onPress = () => {
Alert.alert('Will capture the badge using the camera');
};
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Button
onPress={onPress}
title="Capture Badge"
color="#841584"
accessibilityLabel="Capture a Customer's ID via a picture of their badge"
/>
<WebView
source={{uri: "www.example.com"}}
/>
</View>
);
}
Basically, what do I need to put in onPress so that I can take a picture and then send it to our algorithm (the algorithm will be just a function call at the end of onPress)? I've done research on using a camera in react native, but everything is taking about rendering a camera in the view. I only want to open a camera view if a user taps the "Capture Badge" button at the top of the app.

You can use react-native-image-cropper-picker. If I understood you correctly, you want to be able to launch the camera and then as a promise, send the image to your object detection algorithm. With this library you can launch the camera as follows:
openCamera(){
ImagePicker.openCamera({
width: 300,
height: 400,
cropping: true
}).then(image => {
//Your image
console.log(image);
});
}

Related

How to open all URL inside WebView not in external browser?

I am new to React native and I am trying to open my webpages(page1,page2) inside webview using react native, and my component's webview in the below example.
Here page1 contains button on clicking that button, page2 is opening in child window in external browser.
Can somebody please tell me how to open page2 inside the webview, so that the user can get a good experience?
Example: Component 1
{
<WebView
scalesPageToFit
startInLoadingState={true}
renderLoading={() => { return <Loading/> }}
**source={{uri:"url to page1"}}**
onShouldStartLoadWithRequest={request => {
return request.url.startsWith(domain);
}}
style={styles.web}
javaScriptEnabledAndroid={true}
javaScriptEnabled={true}
originWhitelist={[domain+"*"]}
/>
}
I found the below solution but was not able to implement it in my scenario.
https://github.com/facebook/react-native/pull/6886
I found the answer, this happened because of the latest react-native-webview version.
setSupportMultipleWindows={true} becomes true and in my case, it should be false.

Swipe to next screen (infinite)

I have a calendar section in my app where I want to be able to swipe right or left to go to the next or previous day.
I know that you can use createMaterialTopTabNavigator from React Navigation to do something similar, but I'm not sure if it would work in this specific scenario (where I would have an infinite number of screens and wouldn't be able to predefine them).
I also considered using react-native-gesture-handler's Swipeable component to navigate to the next/previous day screen on a left/right swipe but I'm not sure if this is the easiest/best way to approach this problem.
As you mentioned, you can use Tabs or Swipable. There are some other options like using <ifaram> or <WebView> and using a web URL instead of RN components but it's can be tricky and hard to manipulate.
As a simple solution, you can use carousels instead of using multi screen defining navigation. It's very simple. assume that your screens are an image in an image gallery and you can swipe left/right.
There are many libraries, one of the best ones is: react-native-snap-carousle
Take a look at it's example:
import Carousel from 'react-native-snap-carousel';
export class MyCarousel extends Component {
_renderItem = ({item, index}) => {
return (
<View style={styles.slide}>
<Text style={styles.title}>{ item.title }</Text>
</View>
);
}
render () {
return (
<Carousel
ref={(c) => { this._carousel = c; }}
data={this.state.entries}
renderItem={this._renderItem}
sliderWidth={sliderWidth}
itemWidth={itemWidth}
/>
);
}
}
So you can pass a screen/page as _renderItem to the Carousel

How to prerender a component in react-navigation before switching to it?

Inside my StackNavigator, one of the components includes web content with a long loading time. However, this screen will only be shown late in my navigation flow.
How can I use this time to render my component in the background before finally switching to it?
I couldn't find anything comparable to ReactDOM.render in React Native that would allow me to render it manually.
I am not aware of any option in react-navigation to preload a screen that is not displayed, except maybe when the screen is part of a tab navigator.
Depending on what is slowing down the rendering, you might be able to do some actions in the first screen and later pass the results to the second screen using a navigation parameter.
For instance, if you are fetching data from an api in the second screen, you could fetch this data in the first screen and pass it to the second one:
this.props.navigation.navigate('SecondScreen', { data: this.data });
If it is a component, you could also try to build it in the first screen and pass it in the same fashion:
this.props.navigation.navigate('SecondScreen', { component: this.component });
If you are rendering a WebView in the second screen, what can help is to render the WebView in the first screen too, but with no width or height. The WebView will not be displayed but the website data will be fetched and cached, making the real render more efficient:
render() {
return (
<View>
<WebView source={{ uri: 'https://github.com/facebook/react-native' }} style={{ height: 0, width: 0 }} />
{this.renderCurrentScreen()}
</View>
);
}

In react-native-video how can you disable the seek function?

I am trying to disable the seek function on react native video. I have a full video that I want to preview for 30 seconds. In order to do this I want to disable the seek button so a user cannot skip through the video.
I have tried giving onSeek the value of function that exits the video player however this does not seem to do anything.
if(!loading) {
return <Video source={{uri: uri}} // Can be a URL or a local file.
onFullscreenPlayerDidDismiss={this.onDismiss}
preferredPeakBitrate={this.state.preferredPeakBitrate}
ref={(player) => {
if(!this.state.playing && player) {
player.presentFullscreenPlayer()
this.setState({ playing: true })
}
}} // Store reference
rate={1.0} // 0 is paused, 1 is normal.
volume={1.0} // 0 is muted, 1 is normal.
muted={false} // Mutes the audio entirely.
paused={false} // Pauses playback entirely.
resizeMode="cover" // Fill the whole screen at aspect ratio.*
repeat={false} // Repeat forever.
playInBackground={true} // Audio continues to play when app entering background.
playWhenInactive={true} // [iOS] Video continues to play when control or notification center are shown.
ignoreSilentSwitch={"ignore"} // [iOS] ignore | obey - When 'ignore', audio will still play with the iOS hard silent switch set to silent. When 'obey', audio will toggle with the switch. When not specified, will inherit audio settings as usual.
progressUpdateInterval={PROGRESS_MILLISECONDS} // [iOS] Interval to fire onProgress (default to ~250ms)
onError={this.onVideoError} // Callback when video cannot be loaded
onProgress={this.onProgress}
onLoadStart={this.onStart}
onEnd={this.stopPlaybackPing}
/>
} else {
return <View />
}
}
Short answer: No, you can't.
You called presentFullscreenPlayer() to play the video, unfortunately, you can't disable any buttons on the player. Because that's the default player made by Apple if you're running your app on iPhone, not by the people who created react-native-video, and I don't believe there's any public API that allows you to do so.
What you can do, however, is to write your own full screen player, with any button you want/don't want on there. Here's some hint:
Create a custom component called CustomVideo, which takes the url of the video as a prop:
// CustomVideo.js file
import React, { PureComponent } from 'react';
import { ... } from 'react-native';
import Video from 'react-native-video';
export class CustomVideo extends PureComponent {
constructor(props) {
super(props)
this.state = {
// Have any state you want here, for example
paused: false,
played: 0,
duration: 0,
isFullscreen: false
}
}
render() {
const { url } = this.props;
const { paused, played, duration, isFullscreen } = this.state;
return(
<View style={{ ... }}>
<Video
source={{ uri: url }}
...
/>
// =======> Here, you add your custom buttons <=======
// Suppose you want a pause/play button
<TouchableOpacity onPress={this.toggleVideo}>
<Text>{paused ? "Play" : "Pause"}</Text>
</TouchableOpacity>
// If you want a progress indicator, which users
// can use to skip videos, then use `Slider` component
<Slider
value={...}
step={...}
onValueChange={(value) => ...}
/>
// Here, you toggle whether you want to play the video
// in full screen mode, if so, render it in a modal
// Also, add a full screen toggle button to the video
// the same way you add a play/pause button
<Modal visible={isFullscreen}>
<View>
<Video ... />
</View>
</Modal>
</View>
);
}
}
So, next time, when you want render a video, instead of calling <Video source={{ uri: '...' }} />, you can call your <CustomVideo url='https://....' /> component.

React Native - Interactive initial page

I'm interested in having a view which initially loads with my React Native app that essentially has nested components in it. These components will give visual queues to the user as to what state the app is in, eg: still loading data from the server, etc. Basically, it's not just a static splash screen. I might also add some kind of spinner/progress bar, eg: other animated components.
There are solutions out there for static splash screens that initially show while your app loads into memory, but I need to be able to load an initial component, and then remove it when the application's data is ready to go. Is there a convention/pattern to follow in order to achieve this? Is there a way to mount a component, then remove it when it's no longer necessary allowing the rest of the app to be displayed? What's a best practice for this using React Native?
This is what I used to do:
Use <Modal /> to provide your initial, interactive page. It will blocks the screen, with semi-transparent background; If you like it to be full width, just use flex: 1 within the <View /> inside <Modal />.
Use global object / queue for loading status information. My choice is rxjs, then your initial page can just listen to this one source of truth, suggest a BehaviorSubject. So you can subscribe on it for something like:
...
{ tag: 'FetchRemoteData', progress: 10 }
{ tag: 'LoadingComponent', progress: 5 }
{ tag: 'FetchRemoteData', progress: 20 }
...
Read it until match your "load complete" conditions, then close the model.
To make it clear with code.
app.js
render() {
return (
<View>
<InitialBlockingPage />
<YourMainApp />
</View>
);
}
initial-blocking-page.js
constructor(props) {
super(props);
this.state = {
visible: true
};
}
componentDidMount() {
globalQueue.subscribe( () => {
/// pseudo code: until fully loaded
if (fullloaded) this.setState({visible: false});
});
}
render() {
return (
<Modal visible={this.state.visible}>
<SplashScreenWithData />
</Modal>
);
}