Я установил камеру Expo для открытия на средней вкладке с реактивной навигацией. Однако камера открывается только тогда, когда я нажимаю на эту вкладку в первый раз. Если я его выключу и вернусь, это просто черный экран. Также нет кнопки сделать снимок. (Я новичок в реагировании на родное и любопытное кодирование в целом)
'use strict';
import React, { Component } from 'react';
import { createBottomTabNavigator } from 'react-navigation';
import { Camera, Permissions } from 'expo';
import {
AppRegistry,
Dimensions,
StyleSheet,
Text,
TouchableOpacity,
View,
Button
} from 'react-native';
class HomeScreen extends React.Component {
render() {
return (
<View style = {{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
}
class CameraView extends React.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 }} type = {this.state.type}>
<View
style = {{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<TouchableOpacity
style = {{
flex: 0.1,
alignSelf: 'flex-end',
alignItems: 'center',
}}
onPress = {() => {
this.setState({
type: this.state.type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back,
});
}}>
<Text
style = {{ fontSize: 18, marginBottom: 10, color: 'white' }}>
{' '}Flip{' '}
</Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
}
}
class SettingsScreen extends React.Component {
render() {
return (
<View style = {{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
}
export default createBottomTabNavigator({
Home: HomeScreen,
Camera:CameraView,
Settings: SettingsScreen
});
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
top: 250
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
padding: 15,
paddingHorizontal: 20,
alignSelf: 'center',
margin: 20
}
});





У меня была проблема.
Этот код решил это для меня:
import { withNavigationFocus } from 'react-navigation'
render() {
const { isFocused } = this.props
return (
<View>
{ isFocused && <RNCamera ... /> }
</View
)
}
export default withNavigationFocus(Camera)
Я заставил его работать, используя NavigationEvents, чтобы определить, находится ли вкладка в фокусе, и оттуда смонтировать и отключить камеру. Это также освобождает камеру, если вам нужно использовать ее на другом экране. Вот что я бы сделал в вашем примере:
import { NavigationEvents } from 'react-navigation';
...
class CameraView extends React.Component {
constructor(props) {
super(props)
this.state = {
hasCameraPermission: null,
type: Camera.Constants.Type.back,
isFocused:true
};
}
...
render(){
//...your existing if's
} if (this.state.isFocused === false){
return (
<NavigationEvents
onWillFocus = {payload => {
//console.info("will focus", payload);
this.setState({isFocused:true})
}}
onDidBlur = {payload => {
//console.info('did leave',payload)
this.setState({isFocused:false})
}}
/>
)
}
} else {
return (
<View style = {{ flex: 1 }}>
<Camera style = {{ flex: 1 }} type = {this.state.type}>
<NavigationEvents
onWillFocus = {payload => {
//console.info("will focus", payload);
this.setState({isFocused:true})
}}
onDidBlur = {payload => {
//console.info('did leave',payload)
this.setState({isFocused:false})
}}
/>
//...the rest of your camera code
}
Надеюсь, это сработает и для вас
Для этого вам необходимо:
1.
import { NavigationEvents } from 'react-navigation';
state = { loaded: true }
render() {
const { loaded } = this.state;
return (
<View style = {styles.container}>
<NavigationEvents
onWillFocus = {payload => this.setState({loaded: true})}
onDidBlur = {payload => this.setState({loaded: false})}/>
<View style = {styles.cameraArea}>
{loaded && (
<Camera
type = {Camera.Constants.Type.back}
ref = {ref => {
this.camera = ref;
}}
/>
)}
</View>
Идея состоит в том, чтобы скрыть этот вид камеры (onDidBlur-> loaded: false), а затем, когда вы вернетесь (запускается onWillFocus и изменяется загружено на true). Когда вызывается функция render (), она снова показывает <Camera />.
Если у вас есть вопросы, не стесняйтесь спросить.
С React Navigation 5.x
import { useIsFocused } from '@react-navigation/native';
export const CameraView = (props) => {
const isFocused = useIsFocused();
return (
<View>
{ isFocused && <RNCamera /> }
</View>
)
}
Если вы используете RN Expo с React Navigation - Tab Navigator.
Тогда просто используйте unmountOnBlur - unmountOnBlur Документация
Это заставит камеру отключаться при каждом изменении фокуса навигации.
Решил с помощью крючка useIsFocused от react-navigation/native. Я тестировал его на Android, iOS и в Интернете
import { useIsFocused } from '@react-navigation/native';
...
const isFocused = useIsFocused();
...
return (
isFocused && (
<Camera
ref = {(ref) => {
camera = ref;
}}
onBarCodeScanned = {scanned ? undefined : handleBarCodeScanned}
style = {StyleSheet.absoluteFillObject}
/>
)
);
У меня это работает. (Навигация 5.x) если вы используете другой экран для КАМЕРЫ, вы можете легко отключить экран при переходе на другой.
Reason of this behavior : Only one Camera preview can be active at any given time. If you have multiple screens in your app, you should unmount Camera components whenever a screen is unfocused.
<Stack.Screen name = "camera" component = {CameraScreen} options = {{unmountOnBlur: true}}/>
</Stack.Navigator>
Ссылка на документацию: https://docs.expo.io/versions/latest/sdk/camera/
Спасибо.
Это самое простое решение, и оно отлично работает!
Я попытался включить тот же метод в свое приложение, однако получаю сообщение об ошибке
Couldn't find a navigation object. Is your component inside a screen in a navigator. Любая идея, что не так и как это исправить?