How to view multiple capture image horizontally in react native? - javascript

I just want to capture image using camera API
Then Store it in array
then view one by one image horizontally in React native
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableOpacity,
Image,
PixelRatio
} from 'react-native';
import ImagePicker from 'react-native-image-picker';
let ret;
export default class Location extends Component {
constructor(props){
super(props);
this.state = {
latitude: null,
longitude: null,
address: 'address',
MyAddress: null,
error: null,
};
}
state = {
avatarSource: null,
videoSource: null
};
selectPhotoTapped() {
const options = {
quality: 1.0,
maxWidth: 500,
maxHeight: 500,
storageOptions: {
skipBackup: true
}
};
To get Image, I used this.
ImagePicker.showImagePicker(options, (response) => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled photo picker');
}
else if (response.error) {
console.log('ImagePicker Error: ', response.error);
}
else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
}
else {
let source = { uri: response.uri };
// You can also display the image using data:
//let source = { uri: 'data:image/jpeg;base64,' + response.data };
this.setState({
avatarSource: source
});
}
});
}
Then how to process to view list of image like adpater.
return (
<View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
To show the image in one view ,i have done this. i want to view multiple image like view pager.Like [] [] [] []
<TouchableOpacity onPress={this.selectPhotoTapped.bind(this)}>
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
{ this.state.avatarSource === null ? <Text>Select a Photo</Text> :
<Image style={styles.avatar} source={this.state.avatarSource} />
}
</View>
</TouchableOpacity>
</View>
)
}
}
After few hours i have done this
First save image uri in array then show in list..
let dataStorage = [{uri: response.uri}, ...this.state.dataStorage]
this.setState({dataStorage})
<FlatList
horizontal
data={this.state.dataStorage}
renderItem={({ item: rowData }) => {
return (
<View style={[styles.avatar, styles.avatarContainer, {marginBottom: 20}]}>
{ <Image style={styles.avatar} source={{uri:rowData.uri}} /> }
</View>
);
}
}
keyExtractor={(item, index) => index}
/>

Using Expo's ImagePicker this can be achieved.
Below is my code that might help you.
Note: Its performance is slow but it works.
1) state:
constructor(props) {
super(props);
this.state = {
images: []
};
}
2) openCamera function:
openCamera = async () => {
const { status } = await Permissions.askAsync(
Permissions.CAMERA,
Permissions.CAMERA_ROLL
);
this.setState({
hasCameraPermission: status === 'granted',
hasGalleryPermission: status === 'granted'
});
if (this.state.hasCameraPermission && this.state.hasGalleryPermission) {
ImagePicker.launchCameraAsync({
aspect: [1, 1],
quality: 0.2,
base64: true
})
.then(async result => {
if (!result.cancelled) {
await this.setState({
images: this.state.images.concat(result.uri)
});
Alert.alert(
'Add another picture? ',
null,
[
{
text: 'Yes',
onPress: () => this.openCamera()
},
{ text: 'No' }
],
{ cancelable: false }
);
}
console.log(this.state.images);
})
.catch(error => console.log(error));
}
};
3) To display Image:
showImages = () => {
let temp_image = [];
this.state.images.map((item, index) => {
let tempKey = item + '123';
temp_image.push(
<View key={tempKey}>
<View
key={index}
style={{
height: 100,
width: 100,
borderColor: '#dddddd'
}}
>
<Image
key={index}
source={{ uri: item }}
style={{
flex: 1,
flexDirection: 'row',
backgroundColor: 'silver',
padding: 5,
borderRadius: 5,
height: null,
width: null,
margin: 3,
resizeMode: 'cover'
}}
/>
</View>
<View key={index + 1}>
<TouchableOpacity
key={index + 2}
style={{
flex: 1,
justifyContent: 'center',
alignSelf: 'center',
width: '100%'
}}
onPress={() => {
this.removeImage(index);
this.forceUpdate();
}}
>
<Text
key={index + 3}
style={{
alignSelf: 'center',
color: '#CE3C3E',
fontWeight: 'bold'
}}
>
Delete
</Text>
</TouchableOpacity>
</View>
</View>
);
});
console.log('state images: ', this.state.images);
return temp_image;
};
4) To delete image:
removeImage = index => {
Alert.alert('Delete this image?', null, [
{
text: 'Yes',
onPress: () => {
this.state.images.splice(index, 1);
// console.log(this.state.images);
this.forceUpdate();
}
},
{ text: 'No' }
]);
};
5) And in render() function:
<ScrollView horizontal={true} style={{ flex: 1, flexDirection: 'row' }} >
{this.showImages()}
</ScrollView>

Related

FlatList component is not showing result

I am working on a task in which I have to implement infinite scroll paging of 600 dummy records to cards I have coded on FlatList render. So far I have implemented logic using FlatList but not successfully. Help is required where I am doing wrong thus not giving result. Here is the component code:
import React, { Component } from "react";
import { StyleSheet, ActivityIndicator, FlatList, View } from "react-native";
import { Card } from "react-native-elements";
class InfiniteScroll extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
data: [],
dummy: [],
fetchingStatus: false,
setOnLoad: false,
};
this.page = 0;
let onEndReached = false;
}
componentDidMount() {
var toput = [];
for (let i = 0; i < 598; i++) {
toput.push({
name: "KHAN MARKET",
order_no: "ORDER # DBZ-876",
status: "Order Completed",
price: "Total: $14.00",
date: "Dec 19, 2019 2:32 PM",
});
}
this.setState(
{
dummy: toput,
},
() => {
console.log(this.state.dummy);
}
);
this.apiCall();
}
apiCall = () => {
var that = this;
var old = that.page;
that.page = that.page + 10;
console.log(" *********** call " + this.page);
that.setState({ fetchingStatus: true });
that.setState({
data: [...this.state.data, ...this.state.dummy.slice(old, that.page)],
isLoading: false,
fetchingStatus: false,
setOnLoad: true,
});
};
BottomView = () => {
return (
<View>
{this.state.fetchingStatus ? (
<ActivityIndicator
size="large"
color="#F44336"
style={{ marginLeft: 6 }}
/>
) : null}
</View>
);
};
ItemSeparator = () => {
return (
<View
style={{
height: 0.5,
width: "100%",
backgroundColor: "#607D8B",
}}
/>
);
};
render() {
return (
<View>
{this.state.isLoading ? (
<ActivityIndicator size="large" />
) : (
<FlatList
style={{ width: "100%" }}
keyExtractor={(item, index) => index}
data={this.state.data}
ItemSeparatorComponent={this.ItemSeparator}
onScrollEndDrag={() => console.log(" *********end")}
onScrollBeginDrag={() => console.log(" *******start")}
initialNumToRender={8}
maxToRenderPerBatch={2}
onEndReachedThreshold={0.1}
onMomentumScrollBegin={() => {
this.onEndReached = false;
}}
onEndReached={() => {
if (!this.onEndReached) {
this.apiCall(); // on end reached
this.onEndReached = true;
}
}}
renderItem={({ item, index }) => (
<View>
<Card>
<Text
style={{ justifyContent: "flex-start", fontWeight: "bold" }}
>
{item.name}
</Text>
<View style={styles.textview}>
<Text style={styles.orderno}>{item.order_no}</Text>
<Text style={styles.orderstatus}>{item.status}</Text>
</View>
<Text style={styles.amount}>{item.price}</Text>
<View style={styles.textview}>
<Text style={styles.orderno}>{item.date}</Text>
</View>
</Card>
</View>
)}
ListFooterComponent={this.BottomView}
/>
)}
</View>
);
}
}
const styles = StyleSheet.create({
textview: {
marginTop: 5,
flexDirection: "row",
justifyContent: "space-between",
},
orderno: {
flexDirection: "row",
justifyContent: "flex-start",
},
orderstatus: {
flexDirection: "row",
justifyContent: "flex-end",
color: "green",
},
ordercomplete: {
flexDirection: "row",
justifyContent: "flex-end",
color: "red",
},
amount: {
justifyContent: "flex-start",
marginTop: 5,
},
});
export default InfiniteScroll;
I will be very thankful if you can provide solution. Thanks
The thing here is that you are seting your dummy data and calling the apiCall next, the dummy data is not updated yet when you call the apiCall, ande the dummy data is shown as an empty array on the apiCall, you just ned to force some await before calling the function, just change from this:
this.setState(
{
dummy: toput,
},
() => {
console.log(this.state.dummy);
}
);
this.apiCall();
to this:
this.setState(
{
dummy: toput
},
() => {
this.apiCall();
}
);
Another thing I notice is that you are using some bad pratices like setting valuse direct on the class instead of using state and some messing with the scope (that = this), I've made some updates/suggestions in you code that may help with readability:
apiCall = () => {
const newPage = this.state.page + 10;
this.setState({
data: [
...this.state.data,
...this.state.dummy.slice(this.state.page, newPage)
],
isLoading: false,
fetchingStatus: false,
setOnLoad: true,
page: newPage
});
};
I've created a fully working example so you can see some more updates I've made in the code, that may help you as well:
https://codesandbox.io/s/stackoverflow-67166780-321ku?file=/src/App.js

TypeError: undefined is not an object (evaluating '_this.state.data)

The error occurs when I try to close the modal window. on the "Close" button. The error says that _this.state.data [imageKey] .urls' is not an object, but I pass the string.
I am receiving JSON from a custom API endpoint. I was able to iterate over the JSON and output some data, but the problem is with the string reference to the image. I am getting the error:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableWithoutFeedback,
Dimensions,
Modal,
ScrollView,
} from 'react-native';
import ImageElement from './component/ImageElement';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
data: [],
};
}
componentDidMount() {
fetch('https://api.unsplash.com/photos/?client_id=cf49c08b444ff4cb9e4d126b7e9f7513ba1ee58de7906e4360afc1a33d1bf4c0')
.then((response) => response.json())
.then((data) => {
this.setState({
data: data,
});
});
}
// getImage() {
// return this.state.modalImage
// }
setModalVisible = (visible, imageKey) => {
this.setState({ modalImage: this.state.data[imageKey].urls.raw });
this.setState({ modalVisible: visible });
};
render() {
let images = this.state.data.map((val, key) => {
return (
<TouchableWithoutFeedback
key={key}
onPress={() => {
this.setModalVisible(true, key);
}}
>
<View style={styles.imagewrap}>
<ImageElement
author={{ url: val.user.profile_image.small }} // фото автора
imgsource={{ url: val.urls.small }} // работа автора
authorNameProp={val.user.name} // имя автора
></ImageElement>
</View>
</TouchableWithoutFeedback>
);
});
return (
<ScrollView>
<View style={styles.container}>
<Modal
style={styles.modal}
animationType={'fade'}
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {}}
>
<View style={styles.modal}>
<Text
style={styles.text}
onPress={() => {
this.setModalVisible(false);
}}
>
Close
</Text>
<ImageElement imgsource={{ url: this.state.modalImage }}></ImageElement>
</View>
</Modal>
{images}
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
backgroundColor: 'grey',
overflow: 'scroll',
},
imagewrap: {
margin: 5,
padding: 2,
height: Dimensions.get('window').height / 2 - 60,
width: Dimensions.get('window').width / 2 - 10,
},
modal: {
flex: 1,
padding: 10,
backgroundColor: 'rgba(0,0,0, 0.9)',
},
text: {
color: '#fff',
zIndex: 20,
position: 'absolute',
top: 50,
right: 30,
fontSize: 20,
},
user: {
color: '#fff',
zIndex: 20,
position: 'absolute',
top: 20,
left: 10,
},
});
AppRegistry.registerComponent('ImageGallery', () => ImageGallery);
Issue
Seems you missed passing an index in your close handler this.setModalVisible(false), imageKey is undefined, and thus this.state.data[undefined] is undefined and throws error when you access deeper into the nested properties.
Solution
Conditionally access the data value based on the visible value. Clear out the modalImage state when closing the modal.
setModalVisible = (visible, imageKey) => {
this.setState({
modalImage: visible ? this.state.data[imageKey].urls.raw : null,
modalVisible: visible,
});
}
Alternatively you can just use Optional Chaining to do null checks for you.
setModalVisible = (visible, imageKey) => {
this.setState({
modalImage: this.state.data[imageKey]?.urls?.raw,
modalVisible: visible,
});
}

Add WebView via onClick in Expo React-Native

I need a function that creates new screens with a webview in it.
The main screen of my expo app contains a button "add new Page" which links to a page with a form to add domain, Username, Password.
if this is done, I want a list of pages in my main screen with all pages. for example if I click on "myWebsite1" with the generated link http://user:password#myWebsite1.com this page should be shown in a webview. same for website2, 3 and so on.
Anyone an idea how to do this?
EDIT: I add some code I have right now. For each Task I create, the Domain, User and Password for the webview file should change and be saved at this specific task. (and also open onclick). I turn in a circle
this is my app.js which expo opens first, it contains a Flatlist:
import React, { Component } from "react";
import { AppRegistry, StyleSheet, Text, View, FlatList, AsyncStorage, Button, TextInput, Keyboard, Platform, TouchableWithoutFeedback } from "react-native";
const isAndroid = Platform.OS == "android";
const viewPadding = 10;
const things = {things}
export default class NodeList extends Component {
state = {
tasks: [ ],
text: ""
};
changeTextHandler = text => {
this.setState({ text: text });
};
addTask = () => {
let notEmpty = this.state.text.trim().length > 0;
if (notEmpty) {
this.setState(
prevState => {
let { tasks, text } = prevState;
return {
tasks: tasks.concat({ key: tasks.length, text: text }),
text: ""
};
},
() => Tasks.save(this.state.tasks)
);
}
};
deleteTask = i => {
this.setState(
prevState => {
let tasks = prevState.tasks.slice();
tasks.splice(i, 1);
return { tasks: tasks };
},
() => Tasks.save(this.state.tasks)
);
};
componentDidMount() {
Keyboard.addListener(
isAndroid ? "keyboardDidShow" : "keyboardWillShow",
e => this.setState({ viewMargin: e.endCoordinates.height + viewPadding })
);
Keyboard.addListener(
isAndroid ? "keyboardDidHide" : "keyboardWillHide",
() => this.setState({ viewMargin: viewPadding })
);
Tasks.all(tasks => this.setState({ tasks: tasks || [] }));
}
render() {
return (
<View
style={[styles.container, { paddingBottom: this.state.viewMargin }]}
>
<Text style={styles.appTitle}>Nodes</Text>
<FlatList
style={styles.list}
data={this.state.tasks}
renderItem={({ item, index }) =>
<View>
<View style={styles.listItemCont}>
<TouchableWithoutFeedback onPress={() => Linking.openURL('')}>
<Text style={styles.listItem}>
{item.text}
</Text>
</TouchableWithoutFeedback>
<Button color= "#00BC8C" title="✖" onPress={() => this.deleteTask(index)} />
</View>
<View style={styles.hr} />
</View>}
/>
<TextInput
style={styles.textInput}
onChangeText={this.changeTextHandler}
onSubmitEditing={this.addTask}
value={this.state.text}
placeholder="+ add Node"
returnKeyType="done"
returnKeyLabel="done"
/>
</View>
);
}
}
let Tasks = {
convertToArrayOfObject(tasks, callback) {
return callback(
tasks ? tasks.split("||").map((task, i) => ({ key: i, text: task })) : []
);
},
convertToStringWithSeparators(tasks) {
return tasks.map(task => task.text).join("||");
},
all(callback) {
return AsyncStorage.getItem("TASKS", (err, tasks) =>
this.convertToArrayOfObject(tasks, callback)
);
},
save(tasks) {
AsyncStorage.setItem("TASKS", this.convertToStringWithSeparators(tasks));
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#252525",
padding: viewPadding,
paddingTop: 24
},
list: {
width: "100%"
},
listItem: {
paddingTop: 4,
paddingBottom: 2,
fontSize: 18,
color:"#ffff"
},
hr: {
height: 1,
backgroundColor: "gray"
},
listItemCont: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingTop: 10,
},
textInput: {
height: 40,
paddingRight: 10,
paddingLeft: 10,
borderColor: "gray",
borderWidth: isAndroid ? 0 : 1,
width: "100%",
color:"#ffff"
},
appTitle: {
alignItems:"center",
justifyContent: "center",
paddingBottom: 45,
marginTop: 50,
fontSize: 25,
color:"#ffff"
}
});
AppRegistry.registerComponent("NodeList", () => NOdeList);
and here is my second screen, which contains the component for the WebView:
import React, { Component, useState } from "react";
import { BackHandler } from 'react-native';
import { WebView } from 'react-native-webview';
var $ = require( "jquery" );
export default class nodeView extends Component {
constructor(props) {
super(props);
this.WEBVIEW_REF = React.createRef();
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
handleBackButton = ()=>{
this.WEBVIEW_REF.current.goBack();
return true;
}
onNavigationStateChange(navState) {
this.setState({
canGoBack: navState.canGoBack
});
}
render(){
return (
<WebView
source={{ uri: `https://${user}:${password}#${domain}` }}
ref={this.WEBVIEW_REF}
style={{ marginTop: 20 }}
onNavigationStateChange={this.onNavigationStateChange.bind(this)}
/>
)
}
}
Create WebView. Create State Which Controls WebView. Add Listener To Button

TypeError: undefined is not an object (evaluating 'this.state.googleResponse.responses[0]')

I am totally new at this, and I am using Google Vision with my React Native app on Expo to label documents. I based it off this project:
https://github.com/crowdbotics-apps/rngooglevisionapi-1400/blob/master/frontend/App.js
And I edited it to use Document Text Detection instead.
However, this error keeps coming up.
The only place I am using this.state.googleResponse.responses[0] in my code is:
render() {
let { image } = this.state;
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.getStartedContainer}>
{image ? null : (
<Text style={styles.getStartedText}>Smart Text Extractor</Text>
)}
</View>
<View style={styles.helpContainer}>
<View style={{ margin: 20 }}>
<Button
onPress={this._pickImage}
title="Pick an image from Gallery"
color="#3b5998"
/>
</View>
<Button
onPress={this._takePhoto}
title="Take a photo"
color="#1985bc"
/>
{this.state.googleResponse && (
<FlatList
data={this.state.googleResponse.responses[0].fullTextAnnotation}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.description}
</Text>
)}
/>
)}
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
</View>
</ScrollView>
</View>
);
My entire code is
import React, { Component } from 'react';
import {
View,
Image,
Text,
StyleSheet,
ScrollView,
ActivityIndicator,
Button,
FlatList,
Clipboard
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import * as Permissions from 'expo-permissions';
import uuid from 'uuid';
import Environment from './src/config/environment';
import firebase from './src/config/firebase';
//console.disableYellowBox = true;
async function uploadImageAsync(uri) {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
blob.close();
return await snapshot.ref.getDownloadURL();
}
export default class App extends Component {
state = {
image: null,
uploading: false,
googleResponse: null
};
async componentDidMount() {
await Permissions.askAsync(Permissions.CAMERA_ROLL);
await Permissions.askAsync(Permissions.CAMERA);
}
organize = array => {
return array.map(function(item, i) {
return (
<View key={i}>
<Text>{item}</Text>
</View>
);
});
};
_maybeRenderUploadingOverlay = () => {
if (this.state.uploading) {
return (
<View
style={[
StyleSheet.absoluteFill,
{
backgroundColor: 'rgba(255,255,255,0.4)',
alignItems: 'center',
justifyContent: 'center'
}
]}
>
<ActivityIndicator color="#fff" animating size="large" />
</View>
);
}
};
_maybeRenderImage = () => {
let { image, googleResponse } = this.state;
if (!image) {
return;
}
return (
<View
style={{
marginTop: 20,
width: 250,
borderRadius: 3,
elevation: 2
}}
>
<Button
style={{ marginBottom: 10 }}
onPress={() => this.submitToGoogle()}
title="Analyze!"
/>
<View
style={{
borderTopRightRadius: 3,
borderTopLeftRadius: 3,
shadowColor: 'rgba(0,0,0,1)',
shadowOpacity: 0.2,
shadowOffset: { width: 4, height: 4 },
shadowRadius: 5,
overflow: 'hidden'
}}
>
<Image source={{ uri: image }} style={{ width: 250, height: 250 }} />
</View>
<Text
onPress={this._copyToClipboard}
onLongPress={this._share}
style={{ paddingVertical: 10, paddingHorizontal: 10 }}
/>
<Text>Raw JSON:</Text>
{googleResponse && (
<Text
onPress={this._copyToClipboard}
onLongPress={this._share}
style={{ paddingVertical: 10, paddingHorizontal: 10 }}
>
{JSON.stringify(googleResponse.responses)}
</Text>
)}
</View>
);
};
_keyExtractor = (item, index) => item.description;
_renderItem = item => {
<Text>response: {JSON.stringify(item)}</Text>;
};
_share = () => {
Share.share({
message: JSON.stringify(this.state.googleResponse.responses),
title: 'Check it out',
url: this.state.image
});
};
_copyToClipboard = () => {
Clipboard.setString(this.state.image);
alert('Copied to clipboard');
};
_takePhoto = async () => {
let pickerResult = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [4, 3]
});
this._handleImagePicked(pickerResult);
};
_pickImage = async () => {
let pickerResult = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3]
});
this._handleImagePicked(pickerResult);
};
_handleImagePicked = async pickerResult => {
try {
this.setState({ uploading: true });
if (!pickerResult.cancelled) {
uploadUrl = await uploadImageAsync(pickerResult.uri);
this.setState({ image: uploadUrl });
}
} catch (e) {
console.log(e);
alert('Upload failed, sorry :(');
} finally {
this.setState({ uploading: false });
}
};
submitToGoogle = async () => {
try {
this.setState({ uploading: true });
let { image } = this.state;
let body = JSON.stringify({
requests: [
{
features: [
//{ type: 'TEXT_DETECTION'}, //maxResults: 5 },
{ type: 'DOCUMENT_TEXT_DETECTION'}//, maxResults: 5 }
],
image: {
source: {
imageUri: image
}
}
}
]
});
let response = await fetch(
'https://vision.googleapis.com/v1/images:annotate?key=' +
Environment['GOOGLE_CLOUD_VISION_API_KEY'],
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: body
}
);
let responseJson = await response.json();
console.log(responseJson);
this.setState({
googleResponse: responseJson,
uploading: false
});
} catch (error) {
console.log(error);
}
};
render() {
let { image } = this.state;
console.log(this.state.googleResponse)
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.getStartedContainer}>
{image ? null : (
<Text style={styles.getStartedText}>Smart Text Extractor</Text>
)}
</View>
<View style={styles.helpContainer}>
<View style={{ margin: 20 }}>
<Button
onPress={this._pickImage}
title="Pick an image from Gallery"
color="#3b5998"
/>
</View>
<Button
onPress={this._takePhoto}
title="Take a photo"
color="#1985bc"
/>
{this.state.googleResponse && (
<FlatList
data={this.state.googleResponse.responses[0].fullTextAnnotation}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.description}
</Text>
)}
/>
)}
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ebebeb',
paddingBottom: 10
},
developmentModeText: {
marginBottom: 20,
color: 'rgba(0,0,0,0.4)',
fontSize: 14,
lineHeight: 19,
textAlign: 'center'
},
contentContainer: {
paddingTop: 30
},
getStartedContainer: {
alignItems: 'center',
marginHorizontal: 50,
marginVertical: 50
},
getStartedText: {
fontSize: 24,
color: '#000',
fontWeight: 'bold',
textAlign: 'center'
},
helpContainer: {
marginTop: 15,
alignItems: 'center'
},
textText: {
fontSize: 20,
fontWeight: '600'
}
});
//export default App;
Any ideas please?
I think google vision response contain text and bounding. Please update the FlatList component.
<FlatList
data={this.state.googleResponse}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.text}
</Text>
)}
/>
Note: Make sure the this.state.googleResponse must be response of vision api. You can check it by using console.log(this.state.googleResponse) in render method.

React Native Camera - Multiple Photos

I am currently using react-native-camera as a library to take pictures. I managed to show and hide a one and only camera component depending on a specific state. I am working on an app that has multiple buttons to take a picture, for example:
Button A (show camera -> take picture -> store value on local state A)
Button B (show camera -> take picture -> store value on local state B)
Button C (show camera -> take picture -> store value on local state C)
I have been breaking my head on how to do this, but can't figure it out.
My code is the following:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View, Button } from 'react-native';
import { RNCamera } from 'react-native-camera';
export default class BadInstagramCloneApp extends Component {
constructor(props){
super(props);
this.state = {
isVisible: false,
value1: null,
value2: null
}
}
render() {
return (
<View style={styles.subcontainer}>
{this.state.isVisible === true
?
<View style={styles.container}>
<RNCamera
ref={ref => {
this.camera = ref;
}}
style={styles.preview}
type={RNCamera.Constants.Type.back}
flashMode={RNCamera.Constants.FlashMode.on}
permissionDialogTitle={'Permission to use camera'}
permissionDialogMessage={'We need your permission to use your camera phone'}
onGoogleVisionBarcodesDetected={({ barcodes }) => {
console.log(barcodes);
}}
/>
<View style={{ flex: 0, flexDirection: 'row', justifyContent: 'center' }}>
<TouchableOpacity onPress={this.takePicture.bind(this)} style={styles.capture}>
<Text style={{ fontSize: 14 }}> SNAP </Text>
</TouchableOpacity>
</View>
</View>
:
<View>
<Button title='PHOTO 1' onPress={this.changeState}/>
<Button title='PHOTO 2' onPress={this.changeState2}/>
<Button title='SHOW RESULTS' onPress={this.showResults}/>
</View>
}
</View>
);
}
changeState = () =>{
this.setState({isVisible: true})
}
changeState2 = () =>{
this.setState({isVisible: true})
}
showResults = () => {
console.log('VALUE1: ' + this.state.value1);
console.log('VALUE2: ' + this.state.value2);
}
takePicture = async function() {
if (this.camera) {
const options = { quality: 0.5, base64: true };
const data = await this.camera.takePictureAsync(options);
console.log(data.uri);
this.setState({isVisible: false});
}
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: 'black'
},
subcontainer: {
flex: 1,
flexDirection: 'column',
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
padding: 15,
paddingHorizontal: 20,
alignSelf: 'center',
margin: 20,
},
});
I would use the state to distinguish which "camera" you are using.
Your initial state:
this.state = {
isVisible: false,
pictureType: null,
value1: null,
value2: null
}
The function to call when a button is called, where each button has a different pictureType:
initTakingPicture = (pictureType) => {
this.setState({
isVisible: true,
pictureType: pictureType
})
}
Your example button:
<Button title='PHOTO 1' onPress={() => this.initTakingPicture("A")}/>
Then in your takePicture function you can check the state to distinguish which type of picture you are taking and save it into the according field:
takePicture = async function() {
if (this.camera) {
const options = { quality: 0.5, base64: true };
const data = await this.camera.takePictureAsync(options);
console.log(data.uri);
let fieldToSave = "value1" // Fallback
if (this.state.pictureType === "A") {
// Operation you need to do for pictureType A
fieldToSave = "value1"
} else if (this.state.pictureType === "B") {
// Operation you need to do for pictureType B
fieldToSave = "value2"
}
this.setState({
isVisible: false,
pictureType: null,
[fieldToSave]: data.uri
});
}
};

Categories

Resources