Create a Horizontal Parallax ScrollView in React Native

Jason Brown
InstructorJason Brown
Share this video with your friends

Social Share Links

Send Tweet
Published 7 years ago
Updated 5 years ago

In this lesson we'll create a Twitter Moments clone with a horizontal parallax image scrolling effect. We'll use Animated.event, and interpolation to make the effect work.

[00:00] We will start by putting ScrollView, dimensions, and animated from React Dev. Next we'll structure width and height from a dimensions.get call, which is a function that takes the parameter window which will return the current dimensions of the phone screen.

[00:18] We will go and set up our state and constructor by typing this.state [inaudible] to an object. We'll create an animated scroll.state variable and assign it a new animated value with default value of zero.

[00:30] Inside of our container, we will create a ScrollView. We will close off our ScrollView. I will add the properties, paging enabled, which will cause the ScrollView to stop on multiples of its width. We will add a horizontal flag scroll event throttle to throttle our event calls to 16 milliseconds.

[00:54] We will add our onscroll, which will be an animated event, which is a function that takes an array. We will grab native event, the content offset, and we will grab the X of the content offset and assign it to this.state.animatedscroll.

[01:17] Now, we will create a new file which we'll call moment.js. Inside of here, we will create a new React Dev component and call it moment. We'll go back to our app and import our new file that we created.

[01:36] We will go down to our ScrollView and inside it, we will do images.map, which takes a function, which will get our image and our I. We'll then return the moment file that we created. We will pass in a key for the index. We will spread our image, so we'll pass on our properties which will include our image and our title.

[02:06] I'll switch over the moment.js file that we created, and I will import animated, dimensions, and touchable without feedback. We'll do the same as we did before. We'll say consts, width, height, and we'll de-structure our dimensions.get call with a window.

[02:31] Now, we'll create a new style sheet. We'll say constyles=stylesheet.create. We will create a style called container, which will have the width and height of the screen and the overflow hidden. I will also create an image style, which will add flex 1, width set to null, and height set to null.

[02:58] I will set up our component structure. I will open this and close it. We will give our outer view styles=container style that we created. We'll now add an animated.image, which will give the source of this.props.image style. We will say styles.image, and also we'll get the resize mode to assign cover. When we refresh our application, we can see that our images are finally loading and the paging is enabled.

[03:31] We will add some styles for our title. We will add a center, we'll add justify content value of center. We will add a text strap style with a background color of RGBA0000 and an opacity of 05.paddingvertical of 10, our title text will be a background color of transparent, font-size 30, color of white, and we will align our text to the center.

[04:17] Now, we will go to outer components. We will add a view, and give it a style. It will be an array. We will say stylesheet.absolutefill, add a left zero, height zero, bottom zero, right zero, with an absolute position, so this will cover the image. We will add our style.center.

[04:41] Inside of here, we will add a view, style=styles.textwrap. Inside of here, we will say, text. We'll do our this.props.title. We will add our style=styles.title. In refresh, we can see that the title of our drink is in the middle of our screen.

[05:09] In order to achieve our parallax effect, we need to add consts animated style, should be an object with a transform key, which takes an array of transforms. We will use the translateX transform. We will pass them, this.props.translateX, which we aren't passing down yet. We will add that to our image.

[05:32] We will move up data bank to our index. We will create a function which we will call consts.getInterperlate. Our function will take the animated scroll, the current index, and the current amount of images that we have.

[05:56] We will set up our interporlation, we will set up our input range, we will say constsinputrange=I-1 * width. This will set up the translateX for the image before it is swiped to. Then, we will say, I * width, which will be the translateX input for the when we are at the image. Then, in addition we will do I + 1 * width, which will be the input range for after we have swiped away from the image.

[06:28] We set up our consts output range. When we are at the first index, we will say 00150 translated. When we are anywhere else, we will say -300, which means the image will be -300 as we are swiping towards it. It will then move towards 0and as we swipe by it, it will be at 150.

[06:52] We will return animatedscroll.interporlate. We'll pass in our input range, our output range, and set extrapolate, clamp, which means, no matter what happens, it will never go past 0300, or 150 on either side.

[07:14] We will go to our ScrollView where we are rendering our moments, we will set up the translateX property, that we are using for our animation. We will call getinterporlate and pass in this.state.animated scroll. We will pass in turn current index and we will pass in images.length. If we refresh our emulator and we swipe, we can see that a translateX effect is happening on both images.

[07:42] Finally, we'll go add a separator style. We'll create a style called separator, which will be a background color of black, position, absolute, to zero, bottom zero, and we will give a width of five.

[08:09] We will scroll to the top and call it, constgetseparator is equal to current index, which will return a view, which we will say is a self-closing view, because we are putting nothing in the middle. We will give it a key of the current index. We will say style=array styles.seperate. We will say our left is I-1 * width -2.5. This will cause our separator to be right in the middle of both images.

[08:57] We need to render them. Inside of our ScrollView, we will say, array.apply null, we'll say length=images.length +1. This will create an empty array with the length of our images + 1 in it, so our separator will render end on the final screen as well. We'll say map, which will be an error function. We will put something, put this here and we will get our index. We'll say, error function get separator, and I will pass in our index.

[09:41] On refresh, we will see that a black bar is rendered in between each of our images.

Nick P
Nick P
~ 7 years ago

What's the package/shortcut being used at 1:25 that builds out a component for you?

Jason Brown
Jason Browninstructor
~ 7 years ago

The package is actually just a bunch of custom snippets I created, you can grab them here https://gist.github.com/browniefed/abc2460df79d9dbae5421cde951e1ed1

To add them go to Code => Preferences => User Snippets Select JavaScript or JavaScript React and you can add them.

Torgeir Haugen
Torgeir Haugen
~ 6 years ago

In your getSeparator function I think it should be left: i * width 2.5? When you do i - 1 your first separator will be one width to the left of the views.

Markdown supported.
Become a member to join the discussionEnroll Today