A stack navigator that lives on a bottom tab contains 2 screens. One screen implements the react-native-camera and the other a modal. I'm trying to make the modal transparent but it fails (it has a white background). That's happening because of the useIsFocused hook that mounts and unmounts my camera component. Do you have any suggestions on how I can solve the issue?
function Scanner(){
return(
<Scan.Navigator headerMode='none' mode='modal'
screenOptions={{
cardStyle: { backgroundColor: 'transparent'},
cardOverlayEnabled: true,
}}
>
<Scan.Screen name='Camera' component={Camera}/>
<Scan.Screen name='ValidationModal' component= {Validation} />
</Scan.Navigator>
)
}
Camera = ({navigation}) => {
const [flash, setFlash] = React.useState(false)
const isFocused = useIsFocused();
const flashOn = ()=> {
setFlash(prevFlash => !prevFlash)
}
barcodeRecognized = ({ barcodes }) => {
barcodes.forEach(barcode => {
const kappa = JSON.parse(barcode.data)
navigation.navigate('ValidationMdal')
})
};
if(isFocused){
return(
<RNCamera
ref={ref => {
this.camera = ref;
}}
type={RNCamera.Constants.Type.back}
captureAudio={false}
flashMode={flash?RNCamera.Constants.FlashMode.torch:RNCamera.Constants.FlashMode.off}
androidCameraPermissionOptions={{
title: 'Permission to use camera',
message: 'We need your permission to use your camera',
buttonPositive: 'Ok',
buttonNegative: 'Cancel',
}}
style={{ flex: 1,width: '100%'}}
onGoogleVisionBarcodesDetected={this.barcodeRecognized}>
<TouchableHighlight style={{position:'absolute', top:10, right:10, borderRadius:50, zIndex:100, backgroundColor:'rgba(255,255,255,0.7)'}} onPress={flashOn} >
<Image source={flash?require("../../images/_Active.png"):require("../../images/_Idle.png")} />
</TouchableHighlight>
</RNCamera>
)
}else if(!isFocused){
return null
}
}
Validation = ({navigation}) =>{
return(
<View style={styles.container}>
<Image style={{flex:1}} source={require('../../green-tick.png')} resizeMode={'contain'} />
<TouchableHighlight style={} title='Dismiss' onPress={()=>navigation.goBack()}>
<Text>OK</Text>
</TouchableHighlight>
</View>
)
}
Related
Please help me out with this problem.
I can able to pick the image from my Local storage. In the Console also it is showing, But I cannot able to display it on the screen.
Here is my code.
import * as ImagePicker from "expo-image-picker";
import React, { useState } from "react";
import {
ActivityIndicator,
Button,
FlatList,
Image,
StyleSheet,
Text,
useWindowDimensions,
View
} from "react-native";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
export default function App() {
const [images, setImages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const pickImages = async () => {
// No permissions request is necessary for launching the image library
setIsLoading(true);
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
// allowsEditing: true,
allowsMultipleSelection: true,
selectionLimit: 10,
aspect: [4, 3],
quality: 1,
});
setIsLoading(false);
console.log(result);
if (!result.canceled) {
setImages(result.uri ? [result.uri] : result.selected);
}
};
return (
<>
<FlatList
data={images}
renderItem={({ item }) => (
<Image
source={{ uri: item.uri }}
style={{ width: 100, height: 100 }}
/>
)}
keyExtractor={(item) => item.uri}
contentContainerStyle={{ marginVertical: 50, paddingBottom: 50 }}
ListHeaderComponent={
isLoading ? (
<View>
<Text
style={{ fontSize: 20, fontWeight: "bold", textAlign: "center" }}
>
Loading...
</Text>
<ActivityIndicator size={"large"} />
</View>
) : (
<Button title="Pick images" onPress={pickImages} />
)
}
/>
</>
);
}
I can able to pick the image from my Local storage. In Console also it is showing, But i cannot able to display it in screen.
Kindly help me out.
It looks like you're already passing the uri into the array. by doing [result.uri] and then in the image you're doing it again item.uri. trying just doing the item.
I want to capture and render 3 different different images In react native app. how can I do this. now I am able to click image but when I click image then same image is rendering 3 times but I want to click image one by one.
here is my code
constructor(props) {
super(props);
this.state = {
resourcePath: {},
singleFile:null,
fileUri:null,
imageArray:{
PAN: null,
ADH: null,
ADH1: null,
},
imageType:'',
evenTry:false,
singleFilePAN:'',
singleFileADH:'',
singleFileADH1:'',
showCamera: false
};
}
requestCameraPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
title: "App Camera Permission",
message:"App needs access to your camera ",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
let options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.launchCamera(options, (res) => {
console.log('Response = ', res);
if (res.didCancel) {
console.log('User cancelled image picker');
} else if (res.error) {
console.log('ImagePicker Error: ', res.error);
} else if (res.customButton) {
console.log('User tapped custom button: ', res.customButton);
alert(res.customButton);
} else {
const source = { uri: res.uri };
console.log('response', res.uri);
const newImageArray = this.state.imageArray;
newImageArray.PAN = res.uri
newImageArray.ADH = res.uri
newImageArray.ADH1 = res.uri
this.setState({imageArray : {...newImageArray}})
this.setState({
filePath: res,
fileData: res.data,
fileUri: res.uri,
singleFilePAN: newImageArray.PAN,
singleFileADH: newImageArray.ADH,
singleFileADH1: newImageArray.ADH1
});
}
})
} else {
console.log("Camera permission denied");
}
} catch (err) {
console.warn(err);
}
};
render() {
return (
<View style={styles.container}>
<View style={styles.container}>
<Image source={{uri: this.state.imageArray.PAN}} style={{width: 100, height: 100}} />
<Image source={{uri: this.state.imageArray.ADH}} style={{width: 100, height: 100}} />
<Image source={{uri: this.state.imageArray.ADH1}} style={{width: 100, height: 100}} />
<TouchableOpacity onPress={this.requestCameraPermission} style={styles.button}>
<Text style={styles.buttonText}>Launch Camera Directly</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.uploadImage} style={styles.button} >
<Text style={styles.buttonText}>फोटो अपलोड कीजिए</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
please ignore this. I want to capture and render 3 different different images In react native app. how can I do this. now I am able to click image but when I click image then same image is rendering 3 times but I want to click image one by one. I want to capture and render 3 different different images In react native app. how can I do this. now I am able to click image but when I click image then same image is rendering 3 times but I want to click image one by one.
What you are doing in your code is basically setting up the same image uri to all three entries of you array, which is why the rendered images are all the same
newImageArray.PAN = res.uri //this is the same as the ones bellow
newImageArray.ADH = res.uri
newImageArray.ADH1 = res.uri
What you can do is add image to array once taken, and then do a map on the image array like this in your render function
imageArray.map((x) => <Image source={{uri: x.uri}} style={{width: 100, height: 100}} />)
When I am trying to pass data from Login screen to MyProfile screen then I got undefined value.
I am confused that why I am getting undefined value ?
Here is code of my main navigation files.
route.js
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer, getFocusedRouteNameFromRoute } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { createDrawerNavigator } from "#react-navigation/drawer";
import LoginScreen from "./../screens/Login/index.js";
import MyProfileScreen from "../screens/MyProfile/index.js";
import AboutUsScreen from "../screens/AboutUs/index.js";
import SettingScreen from "../screens/Setting/index.js";
import { Image, StyleSheet, View, TouchableOpacity } from "react-native";
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import { RFValue } from "react-native-responsive-fontsize"
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
const NavigationDrawerStructure = (props) => {
const toggleDrawer = () => {
props.navigationProps.toggleDrawer();
}
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={() => toggleDrawer()}>
<Image
source={{ uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png' }}
style={{
width: 25,
height: 25,
marginLeft: 5
}}
/>
</TouchableOpacity>
</View>
)
}
const geHeaderTitle = (route) => {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'MyProfileScreen';
switch (routeName) {
case 'MyProfileScreen':
return 'Profile';
case 'AboutUsScreen':
return 'AboutUs';
case 'SettingScreen':
return 'Setting';
}
}
const BottomTab = () => {
return (
<Tab.Navigator initialRouteName="MyProfileScreen"
tabBarOptions={{
activeTintColor: "red",
labelStyle: {
fontSize: RFValue('14'),
marginTop: 5
},
style: { height: hp('11') }
}}
>
<Tab.Screen
name="MayProfileScreen"
component={MyProfileScreen}
options={{
tabBarLabel: 'Profile',
tabBarIcon: ({ focused }) => (
focused ?
<Image source={require('./../../asstes/images/profile.png')} style={styles.activeImg} /> :
<Image source={require('./../../asstes/images/profile.png')} style={styles.deActiveImg} />
)
}}
/>
<Tab.Screen
name="AboutUsScreen"
component={AboutUsScreen}
options={{
tabBarLabel: 'AboutUs',
tabBarIcon: ({ focused }) => (
focused ?
<Image source={require('./../../asstes/images/aboutus.png')} style={styles.activeImg} /> :
<Image source={require('./../../asstes/images/aboutus.png')} style={styles.deActiveImg} />
)
}}
/>
<Tab.Screen
name="SettingScreen"
component={SettingScreen}
options={{
tabBarLabel: 'Setting',
tabBarIcon: ({ focused }) => (
focused ?
<Image source={require('./../../asstes/images/setting.png')} style={styles.activeImg} /> :
<Image source={require('./../../asstes/images/setting.png')} style={styles.deActiveImg} />
)
}}
/>
</Tab.Navigator>
)
}
const HomeStack = ({ navigation }) => {
return (
<Stack.Navigator initialRouteName="LoginScreen">
<Stack.Screen name="LoginScreen" component={LoginScreen} options={{ headerShown: false }} />
<Stack.Screen name="MyProfileScreen" component={BottomTab}
options={({ route }) => ({
headerTitle: geHeaderTitle(route),
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
title: 'Profile',
headerStyle: { backgroundColor: '#f4511e' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' }
})}
/>
<Stack.Screen name="AboutUsScreen" component={AboutUsScreen}
options={{
title: 'AboutUS',
headerStyle: { backgroundColor: '#f4511e' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' }
}} />
<Stack.Screen name="SettingScreen" component={SettingScreen}
options={{
title: 'Setting',
headerStyle: { backgroundColor: '#f4511e' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' }
}}
/>
</Stack.Navigator>
)
}
const AboutUsStack = ({ navigation }) => {
return (
<Stack.Navigator initialRouteName="AboutUsScreen"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: { backgroundColor: '#f4511e' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' }
}}
>
<Stack.Screen name="AboutUsScreen" component={AboutUsScreen} options={{ title: 'AboutUs' }} />
</Stack.Navigator>
)
}
const SettingStack = ({ navigation }) => {
return (
<Stack.Navigator initialRouteName="SettingScreen"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: { backgroundColor: '#f4511e' },
headerTintColor: '#fff',
headerTitleStyle: { fontWeight: 'bold' }
}}
>
<Stack.Screen name="SettingScreen" component={SettingScreen} options={{ title: 'Setting', }} />
</Stack.Navigator>
)
}
const Navigation = () => {
return (
<NavigationContainer>
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: { marginVertical: 5 }
}}
>
<Drawer.Screen name="HomeStack" options={{ drawerLabel: 'Profile' }} component={HomeStack} />
<Drawer.Screen name="AboutUsStack" component={AboutUsStack} options={{ drawerLabel: 'AboutUs' }} />
<Drawer.Screen name="SettingStack" component={SettingStack} options={{ drawerLabel: 'Setting' }} />
</Drawer.Navigator>
</NavigationContainer>
)
}
const styles = StyleSheet.create({
activeImg: {
height: hp('4.8'), width: wp('8.5'), marginTop: 10, borderRadius: 12, tintColor: 'red'
},
deActiveImg: {
height: hp('4.8'), width: wp('8.5'), marginTop: 10, borderRadius: 12, tintColor: 'gray'
}
})
export default Navigation;
I am calling below function when user click on Login button.
Here is some lines of code that how I am trying to pass data from Login screen to MyProfile screen
Login screen
const resetTextInput = () => {
setName(null);
setPassword(null);
navigation.navigate('MyProfileScreen', { userName: name, userPwd: password,});
}
<TouchableOpacity style={styles.loginBtn} onPress={() => { resetTextInput() }}>
<Text style={styles.loginBtnTxt}>Login</Text>
</TouchableOpacity>
Here is some lines of code that how I am trying to get data from Login screen to MyProfile screen.
MyProfle screen
useEffect(() => {
console.log("username is-->",JSON.stringify(route?.params?.userName));
console.log("userpassword is-->",JSON.stringify(route?.params?.userPwd));
});
Perhaps pass route.params? as an argument inside your useEffect?
useEffect(() => {
...
},[route.params?]);
That way it'll apply the effect when you navigate into it.
Do you have a multiple stack navigator? If you are at different stack navigator and you want to pass params to a screen from different stack navigator, you have to specify the screen.
For example you are at the AuthStack and you want to navigate to MyProfileScreen from the ProfileStack:
navigation.navigate('ProfileStack', { screen: 'MyProfileScreen', params: { //data here } });
if not, I think you got a typo in your BottomTab component. Change the name of the first tab from "MayProfileScreen" to "MyProfileScreen".
then use this to navigate:
navigation.navigate('MyProfileScreen', { //params here });
When I try to load an image by using require, the image does not load but when I load the same image from a URL, the image loads. Here is the snippet of code that I am calling the image from
class Home extends React.Component {
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator = {false}
showHorizontalScrollIndicator = {false}
>
{this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<div>
<Header title={this.state.user.name} />
<div id='image'>
<Image
source={require('./arrow.png')}
style={styles.image}
/>
</div>
</div>
)}
</ScrollView>
);
}
}
The image is loaded here
<Image
source={require('./arrow.png')}
style={styles.image}
/>
Please make sure that you give the right path to your image.
You can use the source as an object:
<Image source={{ uri: 'something.jpg' }} />
But what you have should work, check your path.
There were few errors here and there, I think you were trying to port ReactJS code to RN and not surprisingly there were few slip-ups like you used div instead and View and small things like that, also boxShadow was not working so I removed that.
After a few tweaks code is working and images are loading.
As I stated earlier, I have omitted the User component and sanityClient, you can implement them later.
Here is the working home.js after changes.
import React from "react";
import {
ScrollView,
ActivityIndicator,
StyleSheet,
Image,
ImageBackground,
View,
} from "react-native";
// import UserList from "./user-list";
import Header from "./header";
// import sanityClient from "";
// import BackButton from "./back-button";
// import User from "./user";
// import {Asset} from 'expo-asset';
// const imageURI = Asset.fromModule(require('./arrow.png')).uri;
// const image = require("./assets/aoeu.jpg");
class Home extends React.Component {
state = {
user: {},
loading: true,
};
componentDidMount() {
// TODO: get users
this.getUser();
}
async getUser() {
// sanityClient
// .fetch(
// `*[ _type == "user" && emailAddress.current == "dwight#viamaven.com"]`
// )
// .then((data) => {
// console.log(data);
// this.setState({ user: data[0], loading: false });
// console.log(this.state.user);
// })
// .catch((err) => console.error(err));
// const res = await fetch("https://randomuser.me/api/?results=20");
// const { results} = await res.json();
// // console.log(results)
// this.setState({users: [...results], loading: false});
}
render() {
return (
<ScrollView
noSpacer={true}
noScroll={true}
style={styles.container}
showVerticalSCrollIndicator={false}
showHorizontalScrollIndicator={false}
>
{!this.state.loading ? (
<ActivityIndicator
style={[styles.centering, styles.gray]}
color="#5d38aa"
size="large"
/>
) : (
<View>
<Header title={"Spidy"} />
<View id="image">
<Image source={require("./arrow.png")} style={styles.image} />
</View>
{/* <User /> */}
</View>
)}
</ScrollView>
);
}
}
var styles = StyleSheet.create({
container: {
backgroundColor: "white",
width: 375,
height: 812,
// top: '50px',
},
centering: {
alignItems: "center",
justifyContent: "center",
padding: 8,
height: "100vh",
},
image: {
width: 50,
height: 50,
marginRight: 20,
// boxShadow: "0px 1px 2px 0px rgba(0,0,0,0.1)",
// boxShadow: "10px 10px 17px -12px rgba(0,0,0,0.75)",
},
});
export default Home;
Zip file containing all the changes: src
Output:
I am trying my react native app on android and iOS using the release mode. unfortunately, there is an animation that doesn't trigger in release mode which works perfectly on debug mode.
i have tried to use the 'useNativeDriver: true' which improved the animation on android but didn't fix the issue
for ref:
"react-native": "0.56.0"
my Drawer.js
toggle = () => {
Animated.timing(this.x_translate, {
toValue: this.state.drawerOpen ? 0 : 1,
duration: this.state.animationDuration,
useNativeDriver: true
}).start();
this.setState({ drawerOpen: !this.state.drawerOpen })
}
render() {
const menu_moveX = this.x_translate.interpolate({
inputRange: [0, 1],
outputRange: [-this.state.width, 0]
});
return (
<Animated.View style={[this.props.style, styles.drawer, {
transform: [
{
translateX: menu_moveX
}
]
}]}>
<ImageBackground
source={require('../images/background.png')}
style={{ width: '100%', height: '100%', alignItems: 'center' }}
>
<View style={styles.blank}></View>
<AutoHeightImage source={require('../images/image.png')} width={0.7 * this.state.width} />
<LineDashboard navigate={this.props.navigate} items={[this.menu[0], this.menu[1]]} sizeIcon={30} />
<LineDashboard navigate={this.props.navigate} items={[this.menu[2], this.menu[3]]} sizeIcon={30} />
<LineDashboard navigate={this.props.navigate} items={[this.menu[4], this.menu[5]]} sizeIcon={30} />
</ImageBackground>
</Animated.View>
)
}
my dashboard.js
componentDidMount() {
this.props.navigation.setParams({
handleThis: () => {
console.log(this.drawer);
this.setState({ loaded: true })
this.drawer.toggle();
}
});
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerTitle: 'Home Page',
headerLeft: (
<TouchableOpacity
onPress={() => {
params.handleThis();
}}
style={{ marginLeft: 20 }}
>
<Icon name="menu" size={25} color="black" />
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity
onPress={() => {
console.log(navigation);
// navigation.goBack(null)
navigation.navigate('Login');
}}
style={{ marginRight: 20 }}
>
<Text style={{ color: 'red' }}>Log Out</Text>
</TouchableOpacity>
)
}
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.page}>
<ScrollView>
<View style={styles.pageContainer}>
<View style={{ height: 30 }} />
<AutoHeightImage source={require('../images/patient_primary_logo_white.png')} width={0.7 * width} />
<View style={styles.separator} />
<DashboardNotificationTile title={'Your Notifications'} onPress={() => navigate('Notifications')}>
<Text>You have 2 new notifications</Text>
<Text>Please click to see more</Text>
</DashboardNotificationTile>
<DashboardTile title={'Your Visits'}>
<Text>You have 1 upcoming visit</Text>
<SimpleButton onPress={() => navigate('ToBook')} title='View All Visits' width={'100%'} style={{ marginTop: 16 }} color={'green'}/>
</DashboardTile>
<DashboardTile title={'Your Expense Claims'}>
<Text>You have 2 open expense claims</Text>
<SimpleButton onPress={() => navigate('Open')} title='View All Expense Claims' width={'100%'} style={{ marginTop: 16 }} />
</DashboardTile>
</View>
</ScrollView>
<DrawerDashboard navigate={navigate} onRef={(ref) => this.drawer = ref} style={this.state.loaded ? { opacity: 1 } : { opacity: 0 }} />
</View >
)
}
in Dashboard.js, i have a headerLeft that should trigger the function handleThis() which doesn't seems to be doing. however, when pressed, the TouchableOpacity component stay 'selected' rather than coming back to its original state.
any suggestion?
thanks
EDIT:
the issue occurs at any time when the debugger is not on. sorry i just discovered it right now. The animation works perfectly if the remote JS debugger is launched.
So, i thought the issue may be the processing time, as the app is working slower when the debugger is on, maybe my handleThis() function was not loaded...
So, I moved the setParams() from the ComponentDidMount to WillMount.
didn't worked :\
Any suggestion?