react-native-video: resizeMode not working in iOS 10

resizeMode='cover' in iOS 9.3 works as expected. In iOS 10.0 the video doesn’t resize to take up the full Video component size so I have blank space at the top and bottom of the video.

What’s actually really interesting is that if I have hot loading on and I switch resizeMode to container and then back to cover it works properly. It seems like it just doesn’t resize when the video first loads.

Same issue with stretch - it does not resize on initial load.

If I add the repeat prop it will resize after the first loop.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 6
  • Comments: 19 (4 by maintainers)

Most upvoted comments

“Interesting” behaviour: when I use the ‘muted’ property the video does resize as expected (we don’t use any sound, it’s a background video)

    <Video source={{ uri: 'myVideo', type: 'mov' }}
            style={{ position: 'absolute', top: 0, left: 0, bottom: 0, right: 0 }}
            resizeMode='cover'
            muted
            repeat
            key='video2' />

Sorry I missed this thread… one sec while I take a look…

I found a hackie workaround that maybe help someone till this is fixed.

componentDidMount() {
  setTimeout(() => this.videoPlayer.seek(99999), 50)
}

render() {
  <Video
    ref={ref => this.videoPlayer = ref}
    source={{ uri: 'video' }}
    resizeMode="stretch"
    repeat
    paused={false}
    volume={0}
    style={styles.videoPlayer} />
}

Maybe this can be related to #331 and #297

@jpgarcia expanding on your hack, here’s a solution that is working for me for repeat and non-repeat videos. You can just import this component instead of react-native-video and it’ll “fix” the issue.

import Video from 'react-native-video'

import React, { Component } from 'react'

const END_TIME = 9999999

export default class VideoPatch extends Component {
  constructor (props) {
    super(props)

    this.state = { paused: false }
    this.passedProps = {}
    // Starts 1 because we're immediately going to skip to second play
    this.playCount = 1
  }

  componentWillMount () {
    // Store passed props that we're overriding
    this.passedProps = {
      repeat: this.props.repeat,
      onEnd: this.props.onEnd,
      onLoad: this.props.onLoad
    }
  }

  componentWillReceiveProps (newProps) {
    const { repeat, onEnd, onLoad } = newProps

    // Updated passed props that we're overriding if they change
    if (repeat || onEnd || onLoad) {
      this.passedProps = {
        repeat: repeat || this.passedProps.repeat,
        onEnd: this.props.onEnd || this.passedProps.onEnd,
        onLoad: this.props.onLoad || this.passedProps.onLoad
      }
    }
  }

  /**
   * Cb on video end that handles when to end the video
   */
  onEnd () {
    if (this.passedProps.repeat) {
      // If the video should repeat, emit onEnd immediately
      this.passedProps.onEnd && this.passedProps.onEnd()
    } else {
      // If the video should not repeat, only emit onEnd after it's finished its second play
      if (this.playCount === 2) {
        this.setState({ paused: true })
        this.passedProps.onEnd && this.passedProps.onEnd()
      } else {
        this.playCount++
      }
    }
  }

  /**
   * Cb on video load
   */
  onLoad () {
    // This fixes video resize by seeking to end of the video
    // Because the video resizes when it finishes the first time
    this.refs.video.seek(END_TIME)
    this.passedProps.onLoad && this.passedProps.onLoad()
  }

  render () {
    return <Video
      ref='video'
      {...this.props}
      paused={this.state.paused || this.passedProps.paused}
      repeat
      onEnd={() => this.onEnd()}
      onLoad={() => this.onLoad()} />
  }
}

Fair warning the above code is definitely a hack. It can mess up iOS <= 9.3 because it calls onEnd twice in the beginning so your video will never play. I’d recommend checking the Device version or using debounce.