当我导航到另一个屏幕时,视频继续播放

问题描述 投票:0回答:4

当我从图库上传视频,然后尝试导航到下一个屏幕时,视频会在后台继续播放。

下面是我的代码:

import React, {PureComponent} from 'react';
import {
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Animated,
  ProgressBarAndroid,
} from 'react-native';
import {RNCamera} from 'react-native-camera';
import Icon from 'react-native-vector-icons/Entypo';
import ImagePicker from 'react-native-image-crop-picker';
import Video from 'react-native-video';
import { withNavigationFocus } from 'react-navigation';

class Shoot extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      recording: false,
      processing: true,
      upload: false,
      galleryVideo: '',
      progress30: '',
      progress60: '',
      progress15: 0,
      video: '',
      progressStatus: 0,
      progressStatus60: 0,
      progressStatus15: 0,
      videoPaused: false
    };
  }
  render() {
    return (
      <View style={styles.container}>
        {this.state.upload == true && (
          <TouchableOpacity
            style={{
              backgroundColor: '#e75480',
              position: 'absolute',
              width: 80,
              height: 30,
              zIndex: 2,
              padding: 5,
              borderRadius: 5,
              right: 0,
              justifyContent: 'center',
              alignContent: 'center',
            }}
            onPress={() => this.props.navigation.navigate('Post', {key: 1})}>
            <Text style={{color: 'white', textAlign: 'center'}}>Next</Text>
          </TouchableOpacity>
        )}

        {this.state.upload == false && (
          <TouchableOpacity
            style={{
              position: 'absolute',
              bottom: 0,
              right: '15%',
              justifyContent: 'center',
              alignItems: 'center',
            }}
            onPress={this.video.bind(this)}>
            <Icon name="image" size={30} color="white" />
            <Text style={{color: 'white', fontWeight: 'bold'}}>Upload</Text>
          </TouchableOpacity>
        )}

        <TouchableOpacity
          onPress={this.take60sVideo.bind(this)}
          style={{
            width: 60,
            height: 60,
            justifyContent: 'center',
            alignContent: 'center',
            position: 'absolute',
            bottom: 0,
            left: '25%',
          }}>
          <Text style={{textAlign: 'center', color: 'red', fontSize: 15}}>
            60s
          </Text>
        </TouchableOpacity>
        <TouchableOpacity
          onPress={this.take15sVideo.bind(this)}
          style={{
            width: 60,
            height: 60,
            justifyContent: 'center',
            alignContent: 'center',
            position: 'absolute',
            bottom: 0,
            left: '5%',
          }}>
          <Text style={{textAlign: 'center', color: 'red', fontSize: 15}}>
            15s
          </Text>
        </TouchableOpacity>
        <TouchableOpacity
          onPress={this.take30sVideo.bind(this)}
          style={styles.capture}></TouchableOpacity>

        {this.state.progress30 === true && (
          <View
            style={{
              width: '100%',
              height: 15,
              top: 0,
              position: 'absolute',
              bottom: 0,
              zIndex: 2,
            }}>
            {/* <Animated.View
              style={
                ([StyleSheet.absoluteFill],
                {backgroundColor: '#8BED4F', width: '50%', height: 10})
              }
            /> */}
            <ProgressBarAndroid
              styleAttr="Horizontal"
              progress={this.state.progressStatus}
              indeterminate={false}
              color="#e75480"
            />
          </View>
        )}
        {this.state.progress60 === true && (
          <View
            style={{
              width: '100%',
              height: 15,
              top: 0,
              position: 'absolute',
              bottom: 0,
              zIndex: 2,
            }}>
            {/* <Animated.View
              style={
                ([StyleSheet.absoluteFill],
                {backgroundColor: '#8BED4F', width: '50%', height: 10})
              }
            /> */}
            <ProgressBarAndroid
              styleAttr="Horizontal"
              progress={this.state.progressStatus60}
              indeterminate={false}
              color="#e75480"
            />
          </View>
        )}

        {this.state.progress15 === true && (
          <View
            style={{
              width: '100%',
              height: 15,
              top: 0,
              position: 'absolute',
              bottom: 0,
              zIndex: 2,
            }}>
            {/* <Animated.View
              style={
                ([StyleSheet.absoluteFill],
                {backgroundColor: '#8BED4F', width: '50%', height: 10})
              }
            /> */}
            <ProgressBarAndroid
              styleAttr="Horizontal"
              progress={this.state.progressStatus15}
              indeterminate={false}
              color="#e75480"
            />
          </View>
        )}
        {this.state.video == '' ? (
          <RNCamera
            ref={(ref) => {
              this.camera = ref;
            }}
            style={styles.preview}
            type={RNCamera.Constants.Type.back}
            flashMode={RNCamera.Constants.FlashMode.on}
            androidCameraPermissionOptions={{
              title: 'Permission to use camera',
              message: 'We need your permission to use your camera',
              buttonPositive: 'Ok',
              buttonNegative: 'Cancel',
            }}
            androidRecordAudioPermissionOptions={{
              title: 'Permission to use audio recording',
              message: 'We need your permission to use your audio',
              buttonPositive: 'Ok',
              buttonNegative: 'Cancel',
            }}
            captureAudio={true}
          />
        ) : (
          <Video
            source={{uri: this.state.video}}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              alignItems: 'stretch',
              bottom: 0,
              right: 0,
              height: '90%',
            }}
            resizeMode="cover"
            repeat={true}
            paused={this.state.videoPaused}
          />
        )}
      </View>
    );
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    return {
      ...prevState,
      videoPaused: !nextProps.navigation.isFocused()
    }
  }
  video = () => {
    ImagePicker.openPicker({
      mediaType: 'video',
    }).then((video) => {
      this.setState({
        galleryVideo: 1,
        video: video.path,
        upload: true,
      });
    });
  };

  take30sVideo = async () => {
    if (this.camera) {
      try {
        const options = {
          quality: 2,
          videoBitrate: 8000000,
          maxDuration: 30,
        };
        const promise = this.camera.recordAsync(options);
        this.setState({progress30: true});
        this.value = setInterval(() => {
          if (this.state.progressStatus <= 1) {
            this.setState({progressStatus: this.state.progressStatus + 0.01});
          }
        }, 100);
        if (promise) {
          this.setState({recording: true});
          const data = await promise;
          this.setState({recording: false, upload: true, progress30: false});
          console.log(data);
          console.log('upload', this.state.upload);
        }
      } catch (error) {
        console.log(error);
      }
    }
  };

  take60sVideo = async () => {
    if (this.camera) {
      try {
        const options = {
          quality: 2,
          videoBitrate: 8000000,
          maxDuration: 60,
        };
        const promise = this.camera.recordAsync(options);
        this.setState({progress60: true});
        this.value = setInterval(() => {
          if (this.state.progressStatus60 <= 1) {
            this.setState({
              progressStatus60: this.state.progressStatus60 + 0.01,
            });
          }
        }, 100);
        if (promise) {
          this.setState({recording: true});
          const data = await promise;
          this.setState({recording: false, upload: true, progress60: false});
          console.log(data);
          console.log('upload', this.state.upload);
        }
      } catch (error) {
        console.log(error);
      }
    }
  };
  take15sVideo = async () => {
    if (this.camera) {
      try {
        const options = {
          quality: 2,
          videoBitrate: 8000000,
          maxDuration: 15,
        };
        const promise = this.camera.recordAsync(options);
        this.setState({progress15: true});
        this.value = setInterval(() => {
          if (this.state.progressStatus15 <= 1) {
            this.setState({
              progressStatus15: this.state.progressStatus15 + 0.01,
            });
          }
        }, 100);
        if (promise) {
          this.setState({recording: true});
          const data = await promise;
          this.setState({recording: false, upload: true, progress15: false});
          console.log(data);
          console.log('upload', this.state.upload);
        }
      } catch (error) {
        console.log(error);
      }
    }
  };
}
export default withNavigationFocus(Shoot);
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    backgroundColor: 'black',
  },
  preview: {
    height: '90%',
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  capture: {
    backgroundColor: '#e75480',
    borderRadius: 40,
    borderWidth: 3,
    borderColor: 'red',
    width: 60,
    height: 60,
    position: 'absolute',
    bottom: 0,
    justifyContent: 'center',
    left: '45%',
    alignContent: 'center',
  },
});

我已经尝试过使用NavigationFocus,但它不起作用,请告诉我是否还有其他方法,也请告诉我是否需要其他说明。

任何建议都会很棒。

react-native react-navigation react-navigation-stack react-native-video
4个回答
1
投票

我终于解决了这个问题,方法是为下一个按钮创建一个函数,并在屏幕导航到另一个屏幕时将暂停状态设置为 true。 希望,这有帮助。


0
投票

将视频屏幕设置为“fullScreenModal”对我有用:

("react-native": "0.71.2", "@react-navigation/native": "^6.1.3", "react-native-video": "^5.2.1")

反应导航堆栈定义:

function Stack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="SomeScreen" component={SomeScreen} />
      <Stack.Screen
        name="FullScreenVideo"
        component={FullScreenVideo}
        options={{ headerShown: false, presentation: "fullScreenModal" }}
        />
    </Stack.Navigator>;
  )
}

全屏视频.jsx

import React from "react";
import Video from "react-native-video";
import { StyleSheet } from "react-native";

export default function FullScreenVideo({ navigation, route }) {
  const videoUri = route.params.uri;
  return (
    <Video
      source={{ uri: videoUri }}
      controls
      onEnd={() => navigation.pop()}
      style={styles.backgroundVideo}
    />
  );
}
var styles = StyleSheet.create({
  backgroundVideo: {
    position: "absolute",
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
  },
});

0
投票

我认为您也可以在卸载组件时杀死或暂停视频:

// Class component
componentWillUnmount() {
  videoRef.seek(0)
  this.setState({isPaused: true})
}

OR

// functional component
useEffect(() => {
    return () => {
       videoRef.current.seek(0)
       setIsPaused(true)
    }
}, [])

您还可以使用 React Native 导航中的方法:

焦点屏幕变化时调用函数

我希望它能帮助别人


0
投票

我创建了一个视频项并在其上添加了 useIsFocused 挂钩,它对我有用,你可以尝试

const VideoPlayer: React.FC<VideoPlayerProps> = ({uri}) => {
  const isFocused = useIsFocused();
  
  if (!isFocused) {
    return null;
  }
  
  return (
    <View style={[styles.container]}>
      <Video
        key={`${uri}`}
        source={{uri}}
        style={styles.video}
        ref={videoRef}
        resizeMode={'contain'}
        paused
        allowsExternalPlayback={false}
        playInBackground={false}
        disableFocus={false}
      />
    </View>
  );
};

© www.soinside.com 2019 - 2024. All rights reserved.