【问题标题】:Expo Camera only opening once with React NavigationExpo Camera 仅使用 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
    }

});

【问题讨论】:

    标签: reactjs camera navigation native expo


    【解决方案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 解决了它。我在 Android、iOS 和 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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-08-19
            • 2017-12-18
            • 1970-01-01
            • 2018-08-20
            • 1970-01-01
            • 1970-01-01
            • 2021-12-10
            • 2019-07-02
            相关资源
            最近更新 更多