I’ve heard of a good picture

  • Vertical screen state

  • The horizontal screen state

Antecedents feed

I have written an introduction to the basic functions of The React-Native Video component before. This time, I will expand the introduction to the use of React-Native Video, including some small problems I encountered in the actual development process and solutions.

start

Based on the needs of the actual product, this video is required not only to play the video, but also to control the video, such as full-screen display, sound adjustment, progress adjustment, progress display, sound, rate and so on.

Full screen

When making fullscreen display, it is mainly adapted to Android system, mainly because Android system does not support the fullscreen attribute of the component. F **k ~ I believe that students who have some knowledge about this component will know this problem. I have looked up relevant information before when implementing it. There are basically two implementations:

  1. By routing to jump into the full screen page Also is to use two different video component, a small, for the current display, a big used for video full-screen, the main problem is that the way interaction, not friendly and screen direction transformation and routing jump together to cause the entire behavior on the display can not acceptable.
  2. I’m going to do it in full screen by changing the layout with the style properties and I feel like this is a better way to do it in the demo, but if you have a slightly more complex nested structure you can’t do it in full screen by setting the style.

The above two is what I saw on the Internet, a known problem, however, one can also meet my needs, can only to full screen covering the first thing I think of is mimicry box, at the right moment, RN and RN – antd the component itself, but my way is through the Modal components create full-screen floating layer to realize the video full-screen.

The implementation process

  1. Component structure First build a video UI with the following structure
<TouchableOpacity
   style={[
     styles.content,
     // This is written to fit the full screen mode, which also uses this component
     isModal && {width: '100%'.height: '100%'}}]// This is what I use to dynamically get the size of the parent element to set the size of the video component.
   onLayout={this.layoutHandle}
   onPress={this.changeShowCtrl} > <Video ref={video => this.video = video} source={{uri}} poster={poster} paused={paused} repeat={true}  onLoad={this.loadHandle} onProgress={this.progressHandle} resizeMode="cover" posterResizeMode="cover" style={styles.video} /> { showCtrl && <View style={styles.ctrl_area}> <TouchableOpacity onPress={this.changePausedCtrl}>  <Image source={ paused ? require('./images/pause_icon.png') : require('./images/start_icon.png') } style={styles.pause_icon} /> </TouchableOpacity> <View style={styles.pregress_area}> <Text style={[styles.time_text, {marginLeft: 8.5}]} > {formatTime (currentTime)} < / Text > < the Slider style = {{flex: 1}} maximumTrackTintColor={'#e7e7e7'} minimumTrackTintColor={'#f1321d'} minimumValue={0} maximumValue={Number(duration)}  onValueChange={this.sliderValueChange} onSlidingComplete={this.sliderChangeComplete} value={currentTime} step={1} // Damn, Android can only barely set the slider's color... thumbTintColor="#fff" /> <Text style={[styles.time_text, {marginRight: 8.5}]} > {formatTime (duration)} < / Text > < TouchableOpacity onPress = {this. ChangeOrientation} > < Image Source ={require('./images/large_screen_icon.png')} style={{width: 13.5, height: 13.5, marginRight: 5}} /> </TouchableOpacity> </View> </View> } </TouchableOpacity>Copy the code

The necessary logic is described below, so you have a rudimentary video component with basic display and control functions.

Because when the video is in a state of full screen, it is already out of the existence of the original location, if the video in directly with the original components, will inevitably lead to the original layout problems, just like what I realize is a list of video, every video to full screen, so I use full screen video Modal nested components, Attached to my normal video component, and the way I did it was, I took it up a notch:

	function videoModalWrapper (wrapped) {
	  return class extends React.Component {
	    state = {
	      fullscreen: false
	    }
	
	    changeFullScreen = (a)= > {
	      const { fullscreen } = this.state
	      
		  // The full screen state of the video should not only coordinate the two video components, but also coordinate the screen orientation, such as the following
	      if (fullscreen) {
	        Orientation.lockToPortrait()
	        this.VideoPlayer.StartLoadingVideo()
	      } else {
	        Orientation.lockToLandscape()
	        this.VideoPlayer.ResetVideo()
	      }
	      this.setState({ fullscreen: !fullscreen })
	    }
	
	    render () {
	      const { fullscreen } = this.state
	
	      return<VideoPlayer ref={ref => this.VideoPlayer = ref} {... ChangeFullScreen ={this.changeFullScreen} /> <Modal Visible ={fullscreen} transparent={true} OnRequestClose ={this.changeFullScreen} > <VideoPlayer {... This. Props} // isModal // Coordinates partial, full-screen playback progress changeFullScreen={this.changeFullscreen} /> </Modal> </View>)}}}Copy the code

The important thing here is to control the playback state of the components when switching between full display and partial display. After all, there are still two separate components. I’m coordinating their playback state in the higher-order component. A full-screen component is unloaded when it is hidden in

, so you should pay more attention to the local component. Mr Obama! I almost forgot, the library Orientation, whether or not the full screen status values are used to control the screen Orientation.

Voice control

I don’t think it’s important that you set the volume of an app component individually on mobile, but I still admire the fact that the author of this component exposed the volume interface for us to call directly with

.

Progress adjustment


:

:

:

:

:

:






	sliderValueChange = currentTime= > {
		this.video.seek(currentTime)
		this.setState({ currentTime })
	}
Copy the code

But that’s probably how it started out… Why not? Because I tried 🥶, because when you manually adjust the progress of the video, the video continues, and the onProgress={this.progresshandle} property fights you for control of the current playback time, I used a temporary value and another

attribute, onSlidingComplete: an event that is called when the user leaves the Slider and completes a progress operation. The temporary value I used to store whether the video was playing before it was adjusted:

	sliderValueChange = currentTime= > {
		const { prePaused, paused } = this.state
		
		// Store the temporary playback status
		if (prePaused === null) {
			this.setState({ prePaused: paused })
		}
		// Pause the video and adjust the progress of the video. After! The progress of the video component ~
		this.setState({
			paused: true,
			currentTime,
		}, () => this.video.seek(currentTime))
	}
	
	// Here here! The slide ends, the video continues to the original state, temporary value restored ~
	sliderChangeComplete = currentTime= > {
		const { prePaused } = this.state
		
		this.setState({
			paused: prePaused,
			prePaused: null,
			currentTime
		})
	}
Copy the code

Why does

expose the event attribute that completes the slide? For me? Or AM I just one of the many encountered this problem, ha ha, anyway useful, anyway, now when the video progress adjustment, there is no smooth, there must be ~

Scenario,

Because the bottom of each routing stack created by createStackNavigator always exists and does not uninstall, this leads to another weird problem. When you have video components at the bottom of multiple routing stacks, they do not disappear, and you can experience a situation where a video feeds on another page 🤯. But it’s also simple to solve, the routing and state management association, so have always been able to get the current in that page, give different page tagged, indicates that it belongs to which pages, when global status updates, not under the current routing will not play in a video, of course, can play is to control you, What I did was expose some of the controls on the video, like play, reset… This is convenient to control anytime and anywhere.

At the same time, the exposed control methods can also help us achieve many effects, such as making relevant video recommendations. You can click down one video after another, which is also the difference in navigation. When you jump to the next page in RN, the previous page will not disappear voluntarily. NavigationEvents />

To come to here

Here is my experience after using this component for a period of time, which is to share, but also to record, I hope to accumulate bit by bit, and one day pat the dirt on my knees and sigh: Lao Tzu stand up ~ 🤪🤪🤪🤪