Is there any way to stick a custom button on the camera view to allow a user to perform some action?
Note:- i am using react-native-image-picker library to pick an image.
You can position an absolute View over the RNCamera view, and put all of your content into that absolute view. For example:
import { RNCamera } from 'react-native-camera';
class TakePicture extends Component {
takePicture = async () => {
try {
const data = await this.camera.takePictureAsync();
console.log('Path to image: ' + data.uri);
} catch (err) {
// console.log('err: ', err);
}
};
render() {
return (
<View style={styles.container}>
<RNCamera
ref={cam => {
this.camera = cam;
}}
style={styles.preview}
>
<View style={styles.captureContainer}>
<TouchableOpacity style={styles.captureBtn} onPress={this.takePicture}>
<Icon style={styles.iconCamera}>camera</Icon>
<Text>Take Photo</Text>
</TouchableOpacity>
</View>
</RNCamera>
<View style={styles.space} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
position: 'relative'
},
captueContainer: {
position: 'absolute'
bottom: 0,
},
captureBtn: {
backgroundColor: 'red'
}
});
This is just an example. You will have to play with css properties to reach the desired layout.
simply add this to your code, remember it should be placed inside, it will make a stylish button with shadow.
<RNCamera> </RNCamera>
<RNCamera>
<View style={{position: 'absolute',
bottom: "50%",
right: "30%",}}>
<TouchableOpacity
style={{
borderWidth:1,
borderColor:'#4f83cc',
alignItems:'center',
justifyContent:'center',
width:"180%",
height:"180%",
backgroundColor:'#fff',
borderRadius:100,
shadowOpacity:1,
shadowRadius:1,
shadowColor:"#414685",
shadowOffset: {
width: 1,
height: 5.5,
},
elevation: 6,
}}
onPress={()=>{Alert.alert('hellowworld')}}
>
<Text>hello World</Text>
</TouchableOpacity>
</View>
</RNCamera>
here you can see the output, it will be on the top of the camera.
Related
I am trying to create a FlatList within a View, but when I set the view's position as Absolute, it takes the total content size of the FlatList. But I want to keep the height of the View as the remaining screen size between Navigation Bar & Bottom bar, but I don't know how to achieve that.
Here is my code:
import React from 'react';
import { View, StyleSheet, SafeAreaView, FlatList, Image, } from 'react-native';
import { DARK_GREY_COLOR_CODE, GREY_COLOR_CODE, MAGENTA_COLOR_CODE } from '../Constant/Constants';
export default class ExplorePage extends React.Component {
_renderTutorialList() {
}
render() {
const sampleNameArray = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'Kinky',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Waves/Loose Curls',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Curly',
image_name: './Images/hairtype_thum_image.png',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d79',
title: 'Coily',
},
];
return (
<SafeAreaView style={{flex:1, }}>
<View style={{ flex: 1, position: 'absolute', width: '100%', backgroundColor: GREY_COLOR_CODE }}>
<FlatList
data={sampleNameArray}
renderItem={({ item }) =>
<View style={{width: '89.3%', height: 302, marginLeft: '5.4%', marginRight: '5.4%', }}>
<Image source={require('../Images/user_icon.png')} style={{ position: 'absolute', width: '100%', height: '90%', borderRadius: 10, backgroundColor: MAGENTA_COLOR_CODE}} />
</View>
}
keyExtractor={item => item.id}
/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});
Please help me out. I am unable to fix it as I am new to the React Native.
Here is the screenshot:
try this out
first render items from Flatlist and return view of Flatlist item
render() {
return (
<View style={{flex: 1}}>
<FlatList
extraData={this.state}
data={sampleNameArray}
keyExtractor={item => {
return item;
}}
renderItem={this.renderItem}
/>
</View>
);
this is your main render method and then render the items and adjust your list style in the next render and use style as described style={styles.stylename}
renderItem = ({item}) => {
return (
<View>
<View style={styles.body}>
<Text style={styles.text}> {item.data1}</Text>
<Text style={styles.text}> {item.data2}</Text>
<Text style={styles.text}> {item.data3}</Text>
</View>
</View>
);
and you can set how you want to render your item , like i do like this
then you can set CSS property to each and every element.
Hope it will gonna work for you 😃
I have just started using React Native with Expo so I am kind of confused. So, I have made a camera component which I imported in the main screen. Everything looks good. But I can't take pictures. I cannot click the snap icon and save the image. Is there a component that I missed?
I have only posted the CameraComponent class below.
Camera.js
class CameraComponent extends Component {
state = {
hasCameraPermission: null,
type: Camera.Constants.Type.back
}
async componentWillMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({ hasCameraPermission: status === 'granted' })
}
render() {
const { hasCameraPermission } = this.state
if (hasCameraPermission === null) {
return <View />
}
else if (hasCameraPermission === false) {
return <Text> No access to camera</Text>
}
else {
return (
<View style={{ flex: 1 }}>
<Camera
style={{ flex: 1, justifyContent: 'space-between' }}
type={this.state.type}
>
<Header
searchBar
rounded
style={{
position: 'absolute',
backgroundColor: 'transparent',
left: 0,
top: 0,
right: 0,
zIndex: 100,
alignItems: 'center'
}}
>
<View style={{ flexDirection: 'row', flex: 4 }}>
<Ionicons name="md-camera" style={{ color: 'white' }} />
<Item style={{ backgroundColor: 'transparent' }}>
<Icon name="ios-search" style={{ color: 'white', fontSize: 24, fontWeight: 'bold' }}></Icon>
</Item>
</View>
<View style={{ flexDirection: 'row', flex: 2, justifyContent: 'space-around' }}>
<Icon name="ios-flash" style={{ color: 'white', fontWeight: 'bold' }} />
<Icon
onPress={() => {
this.setState({
type: this.state.type === Camera.Constants.Type.back ?
Camera.Constants.Type.front :
Camera.Constants.Type.back
})
}}
name="ios-reverse-camera"
style={{ color: 'white', fontWeight: 'bold' }}
/>
</View>
</Header>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 30, marginBottom: 15, alignItems: 'flex-end' }}>
<Ionicons name="ios-map" style={{ color: 'white', fontSize: 36 }}></Ionicons>
<View></View>
<View style={{ alignItems: 'center' }}>
<MaterialCommunityIcons name="circle-outline" // This is the icon which should take and save image
style={{ color: 'white', fontSize: 100 }}
></MaterialCommunityIcons>
<Icon name="ios-images" style={{ color: 'white', fontSize: 36 }} />
</View>
</View>
</Camera>
</View>
)
}
}
}
export default CameraComponent;
The icon in the center i;e circle icon should automatically take and save image.
You can use "onPictureSaved" when the asynchronous takePictureAsync function returns so that you can grab the photo object:
takePicture = () => {
if (this.camera) {
this.camera.takePictureAsync({ onPictureSaved: this.onPictureSaved });
}
};
onPictureSaved = photo => {
console.log(photo);
}
In the view you would have a Camera component that has a ref:
<Camera style={styles.camera} type={this.state.type} ref={(ref) => { this.camera = ref }} >
As well as a button that will call the takePicture function on press:
<TouchableOpacity style={styles.captureButton} onPress={this.takePicture} />
So you need to tell your 'circle icon' to take the picture. First I would add a reference to your camera like so
<Camera style={{ flex: 1 }}
ref={ (ref) => {this.camera = ref} }
type={this.state.type}>
then create a function that actually tells your app to take the photo:
async snapPhoto() {
console.log('Button Pressed');
if (this.camera) {
console.log('Taking photo');
const options = { quality: 1, base64: true, fixOrientation: true,
exif: true};
await this.camera.takePictureAsync(options).then(photo => {
photo.exif.Orientation = 1;
console.log(photo);
});
}
}
Now make your icon have an onPress() to take the photo. I did something like this.
<TouchableOpacity style={styles.captureButton} onPress={this.snapPhoto.bind(this)}>
<Image style={{width: 100, height: 100}} source={require('../assets/capture.png')}
/>
</TouchableOpacity>
You may also want to create a view that renders an image preview or something similar. The Expo documentation has a fairly good example on getting started. Note that Expo creates a cached folder called 'Camera' and that's where the image initially is.
You can do this in a functional component as well using a ref created via a React Hook. Here is an example based on the expo SDK 38 Camera component https://docs.expo.io/versions/v38.0.0/sdk/camera/
import React, { useState, useEffect, useRef } from 'react';
import { Text, View, TouchableOpacity } from 'react-native';
import { Camera } from 'expo-camera';
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
const ref = useRef(null)
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
_takePhoto = async () => {
const photo = await ref.current.takePictureAsync()
console.debug(photo)
}
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type} ref={ref}>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<TouchableOpacity
style={{
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
}}
onPress={() => {
setType(
type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
<Text style={{ fontSize: 18, marginBottom: 10, color: 'white' }}> Flip </Text>
</TouchableOpacity>
<TouchableOpacity
onPress={_takePhoto}
>
<Text>Snap Photo</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
I did not check what the UI for that looks like but the main point is to utilize React.useRef and attach the ref to your <Camera/> component. Then you may call ref.current.takePictureAsync to capture and access a new image. Look below to see the important relevant snippets for capturing a photo.
import React from 'react'
/* ... other imports
*/
export default CameraScene = () => {
/* ... other state and permission logic
*/
const ref = useRef(null)
const _takePhoto = async () => {
const photo = await ref.current.takePictureAsync()
console.debug(photo)
}
return (
<Camera style={{flex: 1}} ref={ref}> /* ...
... other ui logic
*/
</Camera>
)
}
Learn more about useRef here https://reactjs.org/docs/hooks-reference.html#useref)
You'll need to add a ref to the Camera class to be able to call it's takePictureAsync function within your own 'handle' method.
cameraRef = React.createRef();
<Camera ref={this.cameraRef}>...</Camera>
Don't forget ".current" when calling the method of the referenced camera.
handlePhoto = async () => {
if(this.cameraRef){
let photo = await this.cameraRef.current.takePictureAsync();
console.log(photo);
}
}
Then simply call your 'handle' method on a touchable element acting as the photo-snap button.
<TouchableOpacity
style={{width:60, height:60, borderRadius:30, backgroundColor:"#fff"}}
onPress={this.handlePhoto} />
You should be able to see the photo logged in your console.
Are you trying to do this on an actual physical device? You can't shoot pictures with an emulator.
How can I implement #mention in react native's TextInput?
I've tried this react-native-mention but it is not being maintained anymore. There are so many styling issues and callback issues.
What I want is to display custom view inside TextInput. Something like this.
And after tapping on the list I want to display like this:
So far I am able to achieve:
When I type '#' in TextInput user list appear.
And when I tap on user I get username in TextInput
Code:
renderSuggestionsRow() {
return this.props.stackUsers.map((item, index) => {
return (
<TouchableOpacity key={`index-${index}`} onPress={() => this.onSuggestionTap(item.label)}>
<View style={styles.suggestionsRowContainer}>
<View style={styles.userIconBox}>
<Text style={styles.usernameInitials}>{!!item.label && item.label.substring(0, 2).toUpperCase()}</Text>
</View>
<View style={styles.userDetailsBox}>
<Text style={styles.displayNameText}>{item.label}</Text>
<Text style={styles.usernameText}>#{item.label}</Text>
</View>
</View>
</TouchableOpacity>
)
});
}
onSuggestionTap(username) {
this.setState({
comment: this.state.comment.slice(0, this.state.comment.indexOf('#')) + '#'+username,
active: false
});
}
handleChatText(value) {
if(value.includes('#')) {
if(value.match(/#/g).length > 0) {
this.setState({active: true});
}
} else {
this.setState({active: false});
}
this.setState({comment: value});
}
render() {
const {comments} = this.state;
return (
<View style={styles.container}>
{
this.state.active ?
<View style={{ marginLeft: 20}}>
{this.renderSuggestionsRow()}
</View> : null
}
<View style={{ height: 55}}/>
<View style={styles.inputContainer}>
<TextInput
style={styles.inputChat}
onChangeText={(value) => this.handleChatText(value)}
>
{comment}
</TextInput>
<TouchableOpacity style={styles.inputIcon} onPress={() => this.addComment()}>
<Icon type='FontAwesome' name='send-o' style={{fontSize: 16, color: '#FFF'}}/>
</TouchableOpacity>
</View>
</View>
);
}
One simple solution would be to use react-native-parsed-text.
Here is an example:
import * as React from "react";
import { Text, View, StyleSheet } from 'react-native';
import ParsedText from 'react-native-parsed-text';
const userNameRegEx = new RegExp(/#([\w\d.\-_]+)?/g);
export default class Example extends React.Component {
handleNamePress = (name) => {
alert("Pressed username " + name);
}
render() {
return (
<View style={styles.container}>
<ParsedText
style={styles.text}
parse={
[
{pattern: userNameRegEx, style: styles.username, onPress: this.handleNamePress},
]
}
childrenProps={{allowFontScaling: false}}
>
This is a text with #someone mentioned!
</ParsedText>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
text: {
color: 'black',
fontSize: 15,
},
username: {
color: 'white',
fontWeight: 'bold',
backgroundColor: "purple",
paddingHorizontal: 4,
paddingBottom: 2,
borderRadius: 4,
},
});
However, this library doesn't support rendering custom views. The example above is achieved by just pure styling. If you need a custom view you need to implement something yourself. For a long time, it wasn't possible to render arbitrary components embedded inside a text-components. However, this has changed now afaik and we can do stuff like this:
<Text>Hello I am an example <View style={{ height: 25, width: 25, backgroundColor: "blue"}}></View> with an arbitrary view!</Text>
Check both code examples here: https://snack.expo.io/#hannojg/restless-salsa
One important note: You can render the output of the ParsedText or your own custom component inside the TextInput, like this:
<TextInput
...
>
<ParsedText
...
>
{inputValue}
</ParsedText>
</TextInput>
New learner, I have multiple buttons on my screen and and inside same container I have another label, on click I want to show the label and then hide after few seconds.
I am controlling through this.state problem is when event fires it shows all labels and then hides all. I found few solutions like assign ids etc and array for buttons.
But issue is there can be unlimited buttons so thats not the way to go to set state for each button. Or if there is any other possible way.
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Dimensions } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super();
this.state = {
visible: false
}
}
_handleClick = () => {
this.setState({
visible: !this.state.visible
});
setTimeout(() => {
this.setState({
visible: false
});
},2000);
}
render() {
return (
<View style={styles.container}>
<View style={styles.item}>
<TouchableOpacity onPress={this._handleClick}><Text>Button 1</Text></TouchableOpacity>
{this.state.visible && <View style={styles.pic}>
<Text>Pic</Text>
</View>
}
</View>
<View style={styles.item}>
<TouchableOpacity onPress={this._handleClick}><Text>Button 2</Text></TouchableOpacity>
{this.state.visible && <View style={styles.pic}>
<Text>Pic</Text>
</View>
}
</View>
<View style={styles.item}>
<TouchableOpacity onPress={this._handleClick}><Text>Button 3</Text></TouchableOpacity>
{this.state.visible && <View style={styles.pic}>
<Text>Pic</Text>
</View>
}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
item: {
width: Dimensions.get("screen").width / 2,
height: 100,
backgroundColor: "rgba(0,0,0,.5)",
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
marginBottom: 1
},
pic: {
position: 'absolute',
right: 10,
top: 10,
}
});
You can use condition for a simplest way. You can call the functions like this and pass parameter for check condition.
onPress={()=>this._handleClick("any flag")}
Define function like this
_handleClick(flag) {
if(flag == 1) {
this.setState({state:true})
}
}
My goal is to use the react-native-camera and simply show a picture on the same screen, if a picture has been taken. I'm trying to save the picture source as "imageURI". If it exists, I want to show it, if a picture hasn't been taken yet, just show text saying No Image Yet. I've got the camera working, since I can trace the app is saving pictures to the disk. Having trouble with the following:
How to assign the capture functions data to a variable when I take the picture, that I can call later (imageURI).
Don't know how to do an if statement in Javascript to check if a variable exists yet.
import Camera from 'react-native-camera';
export default class camerahere extends Component {
_takePicture () {
this.camera.capture((err, data) => {
if (err) return;
imageURI = data;
});
}
render() {
if ( typeof imageURI == undefined) {
image = <Text> No Image Yet </Text>
} else {
image = <Image source={{uri: imageURI, isStatic:true}}
style={{width: 100, height: 100}} />
}
return (
<View style={styles.container}>
<Camera
captureTarget={Camera.constants.CaptureTarget.disk}
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
{button}
<TouchableHighlight onPress={this._takePicture.bind(this)}>
<View style={{height:50,width:50,backgroundColor:"pink"}}></View>
</TouchableHighlight>
</Camera>
I found the answer to my own question. This is an example of the react-native-camera being used.
https://github.com/spencercarli/react-native-snapchat-clone/blob/master/app/routes/Camera.js
Found this answer in another earlier posted question answered by #vinayr. Thanks!
Get recently clicked image from camera on image view in react-native
Here's the code from the first link:
import React, { Component } from 'react';
import {
View,
StyleSheet,
Dimensions,
TouchableHighlight,
Image,
Text,
} from 'react-native';
import Camera from 'react-native-camera';
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
width: 70,
height: 70,
borderRadius: 35,
borderWidth: 5,
borderColor: '#FFF',
marginBottom: 15,
},
cancel: {
position: 'absolute',
right: 20,
top: 20,
backgroundColor: 'transparent',
color: '#FFF',
fontWeight: '600',
fontSize: 17,
}
});
class CameraRoute extends Component {
constructor(props) {
super(props);
this.state = {
path: null,
};
}
takePicture() {
this.camera.capture()
.then((data) => {
console.log(data);
this.setState({ path: data.path })
})
.catch(err => console.error(err));
}
renderCamera() {
return (
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.disk}
>
<TouchableHighlight
style={styles.capture}
onPress={this.takePicture.bind(this)}
underlayColor="rgba(255, 255, 255, 0.5)"
>
<View />
</TouchableHighlight>
</Camera>
);
}
renderImage() {
return (
<View>
<Image
source={{ uri: this.state.path }}
style={styles.preview}
/>
<Text
style={styles.cancel}
onPress={() => this.setState({ path: null })}
>Cancel
</Text>
</View>
);
}
render() {
return (
<View style={styles.container}>
{this.state.path ? this.renderImage() : this.renderCamera()}
</View>
);
}
};
export default CameraRoute;