Sahadev
Sahadev

Reputation: 1448

Problem: Why react native video does not play video in full screen?

I am creating an application for android and ios in react-native(0.57.7) and using react-native-video to play videos uploaded into vimeo. After integrate react video plugin, tested in both device. In ios it works perfectly but in android, I am not able to play video in full-screen mode. Here is my code for 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,
    },
});

and this is the output screen where I can not play video in full screen:

enter image description here

Please help, What I'm doing wrong ?

Upvotes: 7

Views: 39846

Answers (7)

ADIL AHMED
ADIL AHMED

Reputation: 106

just give it a width of

width:'100%'

Upvotes: 0

Mushtaq Mir
Mushtaq Mir

Reputation: 1

 <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'}]
      }}
    />

Upvotes: 0

Roberto Pinales
Roberto Pinales

Reputation: 1

Had same issue fix it by removing the wrapping and setting just the height to the player, no other library needed and no need to manage the orientation.

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

Upvotes: 0

AKHIL BELLAM
AKHIL BELLAM

Reputation: 21

As @Selva answered we can use variables for video sizes i.e width & height and make it occupy full screen and use a stack to place the video in a stack screen above the current screen and pop it when needed. Even if it's in a flat list.

Upvotes: 0

selva
selva

Reputation: 71

Most of suggestion involves adding additional libraries to achieve fullscreen in react-native-vide for android. Its not really needed.

What we need is set the height and width of to full screen to achieve this. we need to use variable instead of fixed value then setState to refresh the view.

Below is the sample typescript code that works for react-native-video fullscreen:

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,
  },
});

Upvotes: 1

Mudit Gulgulia
Mudit Gulgulia

Reputation: 1266

I was struggling with the same problem couple of days ago but I made it work for me in android. I hope this will help you also.

You will need to install some other package as well that is 1. react-native-video-controls 2. react-native-orientation

now In your Screen where the video will be played.

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"
}
});

I hope this will help you.

Upvotes: 3

Sahadev
Sahadev

Reputation: 1448

I have solved fullscreen of video frame just adding resizeMode on Video component:

<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"
/>

Upvotes: 13

Related Questions