【问题标题】:Problem: Why react native video does not play video in full screen?问题:为什么react native video不全屏播放视频?
【发布时间】:2019-03-09 09:47:09
【问题描述】:

我正在 react-native(0.57.7) 中为 android 和 ios 创建一个应用程序,并使用 react-native-video 播放上传到 vimeo 的视频。集成反应视频插件后,在两个设备上进行了测试。在 ios 中它可以完美运行,但在 android 中,我无法以全屏模式播放视频。这是我的 Android 代码:

import React, { PureComponent } from 'react';
import {
    View,
    Text,
    Image,
    ImageBackground,
    StyleSheet,
    SafeAreaView,
    TouchableOpacity,
    ActivityIndicator
} from 'react-native';

import PropTypes from 'prop-types'

import Video from "react-native-video";
import Orientation from 'react-native-orientation-locker';
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from '../components/Resposive';
import RF from "react-native-responsive-fontsize"

export default class Videoplayer extends PureComponent {


    constructor(props){
        super(props);
        this.state = {
            loading: true,
            videoFileArr:[],
            showPlayer:false,
            playing:false
        }
    }

    componentDidMount() {
        Orientation.lockToLandscape();
        this.fetchVimeoVideo();
    }

    componentWillUnmount() {
        Orientation.lockToPortrait();
    }

    goToHome(){
        Orientation.lockToPortrait();
        this.props.navigation.goBack();
    }

    fetchVimeoVideo = async () => {
        await this.setState({ loading: true });

        const { navigation } = this.props;
        const jsonReceived = navigation.getParam('item', {})
        const url = "https://api.vimeo.com/me/videos/" + jsonReceived.video_link
        console.log(url)
        const response = await fetch(
            url, {
                method: "get",
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    Authorization:"Bearer f9e937d64037e657addcf088f28e6cb5"
                }
            });
        const jsonResponse = await response.json();

        const { files} = jsonResponse;
        if (response.status != 200) {
            alert(response.status)
        }

        console.log(files)
        await this.setState({ videoFileArr:files, loading: false });
    };



    renderOptions = () => {
        if (this.state.loading === true) {
            return (
                <View style={{
                    flex: 1,
                    alignItems: "center",
                    justifyContent: "center"
                }}>
                    <ActivityIndicator size="large" color="#00ff00" />
                    <Text style={{ fontFamily: "Futura Std", fontSize: RF(3.0), fontWeight: "900", color: "#244E25", textAlign: "center" }}>Please wait while we are loading questions for you</Text>
                </View>
            )
        }else if (this.state.videoFileArr.length> 0 && this.state.playing === false) {

            const { navigation } = this.props;
            const jsonReceived = navigation.getParam('item', {})
            return(
                <ImageBackground style={{width:"100%",height:"100%",alignItems:"center",justifyContent:"center"}}  source={{uri:jsonReceived.video_banner}}> 
                    <TouchableOpacity
                        onPress={() => {
                            this.setState({playing:true})
                        }}
                    >
                        <Image source={require("../assets/Common/Play/playIcon.png")}/>
                    </TouchableOpacity>
                </ImageBackground>
            )

        } else if (this.state.videoFileArr.length > 0 && this.state.playing === true) {
            return (
                <View style={styles.container}>
                    <Video source={{ uri:this.state.videoFileArr[0].link}}   // Can be a URL or a local file.
                        ref={ ref => 
                            this.player = ref
                        }                                      // Store reference
                        onBuffer={this.onBuffer}                // Callback when remote video is buffering
                        onError={this.videoError}               // Callback when video cannot be loaded
                        style={styles.backgroundVideo}
                        controls={true}
                        paused={false}
                        fullscreen={true}
                    />
                </View>
            )
        }
    }

    render() {
        return (
            <SafeAreaView style={{ flex: 1 }}>
                <View style={{ flex: 1, overflow: "hidden" }}>


                    <View style={{ flex: 1, backgroundColor: "green" }}>
                        {this.renderOptions()}
                    </View>

                    {/* top navigationBar */}
                    <View
                        style={{
                            position: "absolute",
                            top: 0,
                            left: 0,
                            right: 0,
                            width: "100%",
                            flexDirection: "row",
                            justifyContent: "space-between",
                            alignItems: "center",
                            height: 80,
                            backgroundColor: null
                        }}
                    >
                        <TouchableOpacity onPress={
                            ()=>this.goToHome()
                        }>
                            <Image style={{ margin: 8 }} source={require("../assets/Common/goBack/goBack.png")} />
                        </TouchableOpacity>

                        <TouchableOpacity>
                            <Image style={{ margin: 8 }} source={require("../assets/Common/Star/starOff.png")} />
                        </TouchableOpacity>

                    </View>
                </View>
            </SafeAreaView>
        )
    }
}

const styles = StyleSheet.create({
    container:{ flex: 1, justifyContent: "center"},
    backgroundVideo: {
      position: 'absolute',
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
    },
});

这是我无法全屏播放视频的输出屏幕:

请帮忙,我做错了什么?

【问题讨论】:

    标签: android reactjs react-native


    【解决方案1】:

    我已经解决了视频帧的全屏问题,只需在视频组件上添加 resizeMode:

    <Video source={{ uri:this.state.videoFileArr[0].link}}   // Can be a URL or a local file.
        ref={ ref => 
            this.player = ref
        }                                      // Store reference
        onBuffer={this.onBuffer}                // Callback when remote video is buffering
        onError={this.videoError}               // Callback when video cannot be loaded
        style={styles.backgroundVideo}
        controls={true}
        paused={false}
        fullscreen={true}
        resizeMode="cover"
    />
    

    【讨论】:

    • 我正在使用 "react-native": "0.60.4" 和 "react-native-video": "^5.0.2" 这在 iOS 和 android 上对我不起作用。
    • 这并不能解决 Android 上的全屏问题 - 无论有没有resizeMode,IOS 都能完美运行
    【解决方案2】:

    几天前我也在为同样的问题苦苦挣扎,但我让它在 android 中为我工作。我希望这对你也有帮助。

    您还需要安装一些其他软件包 1. react-native-video-controls 2. react-native-orientation

    现在在播放视频的屏幕上。

    import React, { Component } from 'react'
    import {
    Text,
    StyleSheet,
    StatusBar,
    Dimensions,
    Alert,
    Modal,
    BackHandler,
    TouchableOpacity,
    ToastAndroid,
    } from 'react-native'
    
    import { Container, View, Button, Icon, List, ListItem } from 'native-base';
    import Video from 'react-native-video';
    import Orientation from 'react-native-orientation';
    const sample = require('../assets/demo.mp4');
    
    export default class Player extends Component {
    constructor(props) {
        super(props);
        this.onLoad = this.onLoad.bind(this);
        this.onProgress = this.onProgress.bind(this);
    }
    
    
    state = {
        rate: 1,
        volume: 1,
        muted: false,
        resizeMode: 'contain',
        duration: 0.0,
        currentTime: 0.0,
        active: false,
        modalVisible: false,
        fullScreen: true,
    };
    
    onLoad(data) {
        this.setState({ duration: data.duration });
    }
    
    onProgress(data) {
        this.setState({ currentTime: data.currentTime });
    }
    
    getCurrentTimePercentage() {
        if (this.state.currentTime > 0) {
            return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
        } else {
            return 0;
        }
    }
    
    renderRateControl(rate) {
        const isSelected = (this.state.rate == rate);
    
        return (
            <ListItem>
                <TouchableOpacity onPress={() => { this.setState({ rate: rate }) }}>
                    <Text style={{ fontWeight: isSelected ? "bold" : "normal" }}>
                        {rate}x
    </Text>
                </TouchableOpacity>
            </ListItem>
        )
    }
    
    renderResizeModeControl(resizeMode) {
        const isSelected = (this.state.resizeMode == resizeMode);
    
        return (
            <TouchableOpacity onPress={() => { this.setState({ resizeMode: resizeMode }) 
    }}>
                <Text style={[styles.controlOption, { fontWeight: isSelected ? "bold" : 
    "normal" }]}>
                    {resizeMode}
                </Text>
            </TouchableOpacity>
        )
    }
    setModalVisible = (visible) => {
        this.setState({ modalVisible: visible });
    }
    
    fullScreen = () => {
        Orientation.getOrientation((err, orientation) => {
            if (orientation == 'LANDSCAPE') {
                Orientation.lockToPortrait();
            } else {
                Orientation.lockToLandscape();
            }
        });
    
    }
    
    backAction = () => {
        Orientation.getOrientation((err, orientation) => {
            if (orientation == 'LANDSCAPE') {
                Orientation.lockToPortrait();
            }
        });
    };
    
    componentDidMount() {
        this.backHandler = BackHandler.addEventListener(
            "hardwareBackPress",
            this.backAction
        );
    }
    
    componentWillUnmount() {
        this.backHandler.remove();
    }
    render() {
        const { modalVisible, paused } = this.state
        const url = `https://www.sample- 
     videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4`;
        const flexCompleted = this.getCurrentTimePercentage() * 100;
        const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
        return (
            <View style={styles.container}>
                <StatusBar hidden={true} />
    
                <Video source={sample}
                    style={styles.fullScreen}
                    rate={this.state.rate}
                    paused={this.state.paused}
                    volume={this.state.volume}
                    muted={this.state.muted}
                    resizeMode={this.state.resizeMode}
                    onLoad={this.onLoad}
                    onProgress={this.onProgress}
                    onEnd={() => { alert('Done!') }}
                    controls
                    repeat={true} />
                <View style={[{ left: 0 }, styles.rateControl]}>
                    <Button
                        transparent
                        onPress={() => {
                            this.fullScreen();
                        }}
                    >
                        <Icon type="FontAwesome5" name="compress" style={{ color: "#fff", 
    fontSize: 15 }} />
                    </Button>
                </View>
                <View style={styles.rateControl}>
                    <Button
                        transparent
                        onPress={() => {
                            this.setModalVisible(true);
                        }}
                    >
                        <Icon type="FontAwesome5" name="ellipsis-v" style={{ color: 
    "#fff", fontSize: 15 }} />
                    </Button>
                </View>
                {/* <View style={styles.controls}>
    <View style={styles.generalControls}>
    
    <View style={styles.resizeModeControl}>
    {this.renderResizeModeControl('cover')}
    {this.renderResizeModeControl('contain')}
    {this.renderResizeModeControl('stretch')}
    </View>
    </View>
    
    <View style={styles.trackingControls}>
    <View style={styles.progress}>
    <View style={[styles.innerProgressCompleted, { flex: flexCompleted }]} />
    <View style={[styles.innerProgressRemaining, { flex: flexRemaining }]} />
    </View>
    </View>
    </View> */}
                <Modal
                    animationType="slide"
                    transparent={true}
                    visible={modalVisible}
                    onRequestClose={() => {
                        Alert.alert("Modal has been closed.");
                    }}
                >
    
                    <View style={styles.centeredView}>
                        <View style={styles.modalView}>
                            <View style={styles.closeModal}>
                                <Button
                                    transparent
                                    onPress={() => { this.setModalVisible(!modalVisible); 
    }}
                                >
                                    <Icon name="close" />
                                </Button>
                            </View>
                            <View>
                                <Text style={{ textAlign: 'center', fontWeight: 'bold' 
    }}>Play Rate</Text>
                                <List style={{ flexDirection: 'row', justifyContent: 
    'space-between', alignItems: 'center' }}>
                                    {this.renderRateControl(0.25)}
                                    {this.renderRateControl(0.5)}
                                    {this.renderRateControl(1.0)}
                                    {this.renderRateControl(1.5)}
                                    {this.renderRateControl(2.0)}
                                </List>
                            </View>
                        </View>
                    </View>
                </Modal>
            </View >
        )
    }
    }
    
    const styles = StyleSheet.create({
    backgroundVideo: {
        // position: 'absolute',
        // top: 0,
        // left: 0,
        // bottom: 0,
        // right: 0,
        width: Dimensions.get('window').width,
        height: Dimensions.get('window').width * .6,
    },
    
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'black',
    },
    fullScreen: {
        position: 'absolute',
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
    },
    controls: {
        backgroundColor: "transparent",
        borderRadius: 5,
        position: 'absolute',
        bottom: 20,
        left: 20,
        right: 20,
    },
    progress: {
        flex: 1,
        flexDirection: 'row',
        borderRadius: 3,
        overflow: 'hidden',
    },
    innerProgressCompleted: {
        height: 20,
        backgroundColor: '#cccccc',
    },
    innerProgressRemaining: {
        height: 20,
        backgroundColor: '#2C2C2C',
    },
    generalControls: {
        flex: 1,
        // flexDirection: 'row',
        borderRadius: 4,
        overflow: 'hidden',
        paddingBottom: 10,
    },
    rateControl: {
        flexDirection: 'row',
        position: 'absolute',
        top: 10,
        right: 10
    },
    volumeControl: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'center',
    },
    resizeModeControl: {
        flex: 1,
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'center',
    },
    controlOption: {
        alignSelf: 'center',
        fontSize: 11,
        color: "white",
        paddingLeft: 2,
        paddingRight: 2,
        lineHeight: 12,
    },
    centeredView: {
        flex: 1,
        marginTop: '22%'
    },
    modalView: {
        width: '100%',
        padding: '5%',
        backgroundColor: "white",
        position: 'absolute',
        bottom: 10,
    },
    openButton: {
        backgroundColor: "#F194FF",
        borderRadius: 20,
        padding: 10,
        elevation: 2
    },
    closeModal: {
        alignItems: 'flex-end',
        margin: -10
    },
    textStyle: {
        color: "white",
        fontWeight: "bold",
        textAlign: "center"
    },
    modalText: {
        marginBottom: 15,
        textAlign: "center"
    }
    });
    

    希望对你有所帮助。

    【讨论】:

      【解决方案3】:

      大多数建议涉及添加额外的库以在 react-native-vide for android 中实现全屏。它并不是真正需要的。

      我们需要设置全屏的高度和宽度来实现这一点。我们需要使用变量而不是固定值然后 setState 来刷新视图。

      以下是适用于 react-native-video 全屏的示例打字稿代码:

      import React, {Component} from 'react';
      import {
        View,
        StyleSheet,
        TouchableWithoutFeedback,
        Dimensions,
      } from 'react-native';
      
      import Video from 'react-native-video';
      
      import Icon from 'react-native-vector-icons/FontAwesome';
      import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons';
      
      interface Props {}
      interface States {
        paused: boolean;
        inFullScreen: boolean;
      }
      export default class Sandbox extends Component<Props, States> {
        player: any;
        videoStyle: {minWidth: number; minHeight: number};
      
        constructor(props: Props) {
          super(props);
          this.state = {
            paused: true,
            inFullScreen: false,
          };
          this.videoStyle = {minWidth: 400, minHeight: 400};
        }
        render() {
          return (
            <View style={{height: 400, width: 400}}>
              <Video
                source={{
                  uri:
                    'https://www.radiantmediaplayer.com/media/big-buck-bunny-360p.mp4',
                }} // Can be a URL or a local file.
                ref={(ref: any) => {
                  this.player = ref;
                }} // Store reference
                controls={false}
                paused={this.state.paused}
                resizeMode={'cover'}
                style={this.videoStyle}
              />
              <View style={styles.controls}>
                <TouchableWithoutFeedback
                  onPress={() => {
                    this.setState({paused: !this.state.paused});
                  }}>
                  <Icon name={'play'} size={30} color="#FFF" />
                </TouchableWithoutFeedback>
      
                <TouchableWithoutFeedback
                  onPress={() => {
                    if (!this.state.inFullScreen) {
                      //Orientation.lockToLandscape();
                      this.videoStyle = {
                        minHeight: Dimensions.get('window').height,
                        minWidth: Dimensions.get('window').width,
                      };
                    } else {
                      this.videoStyle = {
                        minHeight: 400,
                        minWidth: 400,
                      };
                    }
      
                    this.setState({inFullScreen: !this.state.inFullScreen});
                  }}>
                  <MaterialIcon name={'fullscreen'} size={30} color="#FFF" />
                </TouchableWithoutFeedback>
              </View>
            </View>
          );
        }
      }
      
      const styles = StyleSheet.create({
        controls: {
          backgroundColor: 'rgba(0, 0, 0, 0.5)',
          height: 48,
          top: 20,
          left: 0,
          bottom: 0,
          right: 0,
          position: 'absolute',
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'space-around',
          paddingHorizontal: 10,
        },
      });
      

      【讨论】:

      • 这个解决方案不是通用的 - 如果视频在 FlatList 中呈现,它将不起作用,因为position: absolute 将被隔离到列表项区域。
      【解决方案4】:

      正如@Selva 回答的那样,我们可以使用视频大小的变量,即宽度和高度,并使其占据全屏,并使用堆栈将视频放在当前屏幕上方的堆栈屏幕中,并在需要时将其弹出。即使它在一个平面列表中。

      【讨论】:

        【解决方案5】:

        通过删除包装并仅设置播放器的高度来解决相同的问题,不需要其他库,也不需要管理方向。

        <Video source={{uri: this.props.videoData.uri}}
               onEnd={this.onVideoEnd}
               style={styles.player}
               controls={true} />
        

        【讨论】:

          【解决方案6】:
           <View
           onStartShouldSetResponder={() => setPaused(!paused)}
              style={{
                marginHorizontal: 10,
                backgroundColor: "black",
                position: "relative",
                transform: [{ rotate: "90deg" }],
                // justifyContent:'center',
                // alignItems:'center'
              }}
            >
              <Video
                onEnd={onEnd}
                onLoad={onLoad}
                onLoadStart={onLoadStart}
                posterResizeMode={"cover"}
                onProgress={onProgress}
                paused={paused}
                ref={(ref) => (videoPlayer.current = ref)}
                resizeMode={'stretch'}
                source={{
                  uri: "url",
                }}
                style={{
                  ...styles.backgroundVideo,
                     height: width,
                  aspectRatio:2
                  // width: "100%"
                  // alignSelf:'center'
                  // transform: [{ rotate: '90deg'}]
                }}
              />
          

          【讨论】:

          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。
          猜你喜欢
          • 1970-01-01
          • 2019-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-24
          • 2022-11-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多