Create Custom Controls for React Native Video

Jason Brown
InstructorJason Brown
Share this video with your friends

Social Share Links

Send Tweet

In this lesson we'll use react-native-vector-icons to add play/paused buttons, a seek bar, and the duration of the video. We'll use the onLoad, onProgress, and onEnd callbacks to track the video progress. We'll use the react-native-progress to create an animated progress bar for us. Finally with TouchableWithoutFeedback we will add a tap to seek interaction to jump to specific times in the video.

Besides React native video, we'll also use React native progress bar as well as React native vector icons. First, we'll MPM install both of those. Once that's complete, we'll need to use the React-native link command to link up all the native pieces for the React native vector icons.

We'll start by setting up some pieces of state. We'll say state equals an object with pause false so the video will start playing, progress of zero, so the beginning of the video, and then the duration of zero which will actually set the duration after a callback that gathers some information about our video.

You can see here that we've imported our video called Light Video from the file system. Now we'll add our video to the render function. I'll use the video from React native video.

We'll add in paused and say, this.state.pause, that we created earlier. We'll say our source is our light video. We'll add the style of width of 100 percent, and we'll add the height here in a second. We use resize mode equals contain which will contain the video and the aspect ratio to the width and the height that we set.

We'll add an on load and make call this.handle load. We'll add an on progress which will be the callback for every time the video ticks. Then we'll add an on end which will get called when the video finishes playing. We'll also add a ref so that we can call seek on it when we need to change the position of the video.

To calculate the height so that the aspect ratio's maintained, we know that our video is 1920 by 1080. First, we'll get the width of our screen, dimensions.get window. Then for our height, we'll say width times 0.5625 which is 1080, the width, divided by the height. That way we can still maintain our aspect ratio of 1920 by 1080.

We place that here, and then refresh this. Now you can see that our video is playing and is the correct width and height.

We already have some styles here, so our controls will have a light dark background. We will then have a height of 48 and position them at the bottom. They will be a flex direction row as well as our main button, and our duration will have some margin on it.

Now we will set up our controls. We'll say view style equals styles.control. Our controls will go in here and sit on top of our video. We will use the touchable without feedback from React native, which just means that we will get an on press, however there will be no indication that anything has changed because we will be switching the play to paused.

We'll use touchable without feedback and add the on press is equal to this.handle main button touch. Inside there, we will have our icon, and name equals. If it's not this.state.paused, that means that we want the paused button to show. Otherwise, we want the play to show.

We'll have a size of 30 and we will make it white. We'll close our touchable without feedback. Now you can see that when we refresh, we have a play button that is on the screen.

Now we'll add our progress bars. We will need another touchable without feedback which on press we'll call this.handle progress press. This way we can attach a listener so that when you press anywhere on the seek bar that it will actually navigate to that position in the video.

We'll then create our progress bar that we imported earlier, and say progress is equal to this.state.progress, which is a value between zero and one. We'll give it a color of white, an unfilled color of RGBA 255, 255, 255.5, which is a white with a 50 percent opacity. We'll have a border color that's also white, a width of 250, and a height of 20.

Now finally, we'll add in our duration which is just going to be a text element with seconds to time. This will take a number of seconds which is why we're saying this.state.progress, which is a number between zero and one and this.state.duration, which will be the number of seconds. Then it will format them in the minutes to seconds.

Now if we refresh this, we can see that we have a pause button, a play bar that is doing nothing as well as our duration formatted in minutes and seconds.

We now have to handle the many callbacks and functions that we have declared here. The first one we'll focus on is the on load. We'll create our handle load function that is a callback that receives information about the video. We'll just call that meta. The piece of meta information that we care about is the duration, so say this.set state duration is equal to meta.duration.

The next one we'll handle is progress. We'll say handle progress is equal to progress. It will send varying information about the progress, but we just care about the current time that the video is playing. Say this.set state progress progress.current time divided by this.state.duration.

When we refresh this, we can see that it's playing and that our countdown is actually ticking along because the progress is being updated and we know the length of the video.

We'll then also set up the handle end. This will allow us to stop the video once it hits the end of the video. We say this.set state paused true. Now when we refresh, once this hits the end, then it will switch over to pause being true so the video will stop playing.

Now we need to set up what happens when our handle main touch button gets called, so when we press play or we press pause. We'll say handle main button touch, and we'll say this.set state. Because we're referencing state, we need to also make this a callback, a updater function for set state. Say state, then we'll return pause is equal to state not state.pause. This will toggle our paused and playing variants.

But if we have already hit the end of our video, therefore our progress will be greater than one and we want to reset back to the beginning of the video. If we then say if this,state.progress is greater than or equal to one, meaning the end of the video, if it has possibly surpassed one, then we'll call this.player.seek zero. This.player references our video element ref here.

Now if we go ahead and refresh this, we can wait for the video to play a little bit, then pause and then also continue playing it. Once it's hit the end, we can press play again, and it resets back to the beginning.

Finally, we need to set up the progress touch capabilities. We'll create our handle progress press. The progress press from the touch without native feedback will return an event. We'll say const position is equal to e.native event.location X. That means that we're getting the location that the button, this progress bar, was touched along the X axis.

We'll then calculate our progress, say const to progress is equal to our position divided by the 250 width of our progress bar times this.state.duration, so that we can calculate the progress times the number of seconds. We'll then say this.player.seek progress. Now if we refresh and press somewhere in the video, we will shoot to that position in the video.