Expo Camera 仅使用 React Navigation 打开一次

Posted

技术标签:

【中文标题】Expo Camera 仅使用 React Navigation 打开一次【英文标题】:Expo Camera only opening once with React Navigation 【发布时间】:2018-11-26 03:00:30 【问题描述】:

我将 Expo 相机设置为在带有反应导航的中间选项卡上打开。但是,仅当我第一次单击该选项卡时,相机才会打开。如果我关闭它并返回它只是一个黑屏。拍照按钮也没有。 (作为一个整体,我是 React Native 和有点编码的新手)

'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
    

);

【问题讨论】:

【参考方案1】:

使用反应导航 5.x

import  useIsFocused  from '@react-navigation/native';

export const CameraView = (props) => 
    const isFocused = useIsFocused();
    return (
       <View>
          isFocused && <RNCamera  />  
       </View>
     )

useIsFocused Documentation

【讨论】:

谢谢,它成功了。可以是“已接受的答案”【参考方案2】:

我遇到了一些问题。

这段代码为我解决了这个问题:

import  withNavigationFocus  from 'react-navigation'

render() 
    const  isFocused  = this.props
    return (
       <View>
          isFocused && <RNCamera  ... />  
       </View
     )



export default withNavigationFocus(Camera)

【讨论】:

【参考方案3】:

要完成这项工作,您需要:

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->加载:false),然后当你回来时(onWillFocus被触发并将加载更改为true)。当调用 render() 函数时,它将再次显示&lt;Camera /&gt;。 如果您有任何问题,请随时提出。

【讨论】:

【参考方案4】:

我通过使用 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.log("will focus", payload);
                        this.setState(isFocused:true)
                    
                    onDidBlur=payload => 
                        //console.log('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.log("will focus", payload);
                        this.setState(isFocused:true)
                    
                    onDidBlur=payload => 
                        //console.log('did leave',payload)
                        this.setState(isFocused:false)
                    
                />
          //...the rest of your camera code
      

我希望它也适合你

【讨论】:

【参考方案5】:

我使用来自react-navigation/native 的钩子useIsFocused 解决了它。我在 androidios 和 Web 上对其进行了测试

import  useIsFocused  from '@react-navigation/native';

...

const isFocused = useIsFocused();

...

return (
    isFocused && (
      <Camera
        ref=(ref) => 
          camera = ref;
        
        onBarCodeScanned=scanned ? undefined : handleBarCodeScanned
        style=StyleSheet.absoluteFillObject
      />
    )
  );

【讨论】:

我试图在我的应用程序中加入相同的方法,但是,我收到了一个错误,Couldn't find a navigation object. Is your component inside a screen in a navigator。任何想法有什么问题以及如何解决这个问题?【参考方案6】:

这对我有用。 (导航 5.x) 如果您为 CAMERA 使用不同的屏幕,您可以在移动到另一个屏幕时轻松卸下屏幕。

此行为的原因:任何时候都只能激活一个相机预览 给定的时间。如果你的应用中有多个屏幕,你应该 每当屏幕失焦时卸载相机组件。

<Stack.Screen name="camera" component=CameraScreen options=unmountOnBlur: true/>
</Stack.Navigator>

文档链接:https://docs.expo.io/versions/latest/sdk/camera/

谢谢。

【讨论】:

这是最简单的修复方法,而且效果很好!【参考方案7】:

如果您将 RN Expo 与 React Navigation - Tab Navigator 结合使用。

然后只需使用unmountOnBlur - unmountOnBlur Documentation

这将强制相机在每次导航焦点更改时卸载。

【讨论】:

以上是关于Expo Camera 仅使用 React Navigation 打开一次的主要内容,如果未能解决你的问题,请参考以下文章

延迟使用 React Native Camera / Expo Camera 捕获图像,设置“处理消息”?

React Native - 从 expo-camera 获取帧

React Native开发之expo中camera的基本使用

Expo XDE React-Native CAMERA_ROLL 权限“未确定”

React Native / Expo - 将图像传递到预览屏幕

无法在 Expo Camera recordAsync 上设置“质量”