React Native Apple App of the day Animation #1 : Setup UI
In this tutorial, we are going to create React Native Shared Element Transition by replicating Apple app of the day as an example. This tutorial will address an interesting aspect of using React Animation and Dimensions to making images look cool. Here, we are not going to use any external react plugins. All the required components like Image, Animated, Dimensions are provided by the react-native package.
The idea is to start with simple React Native project. Then, we are going to add images and wrap the images with different components from the react-native package and configure it to implement react-native shared element transition.
So, let’s get started!!
Start with an empty project
First, we are going to create a starting boilerplate React Native application. For that, we need to run following commands into our desired directory:
>>react-native init <example-app>
After the installation of the blank react-native application is complete, we are going to run the app in our iOS emulator by using the following command:
>>>react-native run-ios
As a result, we will get the following result in our emulator screen:
Adding Image and configuring it
Now, we are going to add images to our app. For that, we need to remove all unnecessary code from our App.js file. Then, we need to add the following code to our App.js file. The images are imported from the image directory. We can create our own image directory into our project source directory, add our own images and then import them in an array constant as given in the code snippet below:
import React from 'react';
import {View} from 'react-native';const images = [
{id: 1, src: require('./image/1.jpeg')},
{id: 2, src: require('./image/2.jpeg')},
{id: 3, src: require('./image/3.jpeg')},
{id: 4, src: require('./image/4.jpeg')},
];
export default class App extends React.Component {
render() {
return <View></View>;
}
}
In the code snippet, above we have only included the images constant and a View component from the react-native package. Hence, the app will appear blank in the emulator if we re-run it.
So, in order to add the imported images into our screen, we are going to replace the View component with ScrollView component so that we can view the images on the screen by scrolling up and down the screen. Then, we are going to map the images on to the screen by using map function which helps us iterate through the array and return the JSX elements. Here, the element we are returning from the map function is the Image component in which the imported images are integrated. For that, we can make use of the code provided in the following code snippet:
import React from 'react';
import {Image, ScrollView} from 'react-native';const images = [
{id: 1, src: require('./image/1.jpeg')},
{id: 2, src: require('./image/2.jpeg')},
{id: 3, src: require('./image/3.jpeg')},
{id: 4, src: require('./image/4.jpeg')},
];
export default class App extends React.Component {
render() {
return (
<ScrollView style={{flex: 1}}>
{images.map(image => {
return <Image key={image.id} source={image.src} />;
})}
</ScrollView>
);
}
}
As a result, we are going to get the following screen in our emulator:
As we can see in the emulator simulation above, the images appear on the screen and hence, are scrollable.
Wrapping the Image up
The next step is to wrap the Image component by using TouchableWithOutFeedBack and Animated View component in order to create an animation when touched. The TouchableWithOutFeedBack component is used to make the images clickable without providing any kind of feedback on the screen while the Animated View component makes images animate with a proper view. Thus, the code to implement this is provided in the code snippet below:
import React from 'react';
import {
Image,
ScrollView,
TouchableWithoutFeedback,
Animated,
} from 'react-native';const images = [
{id: 1, src: require('./image/1.jpeg')},
{id: 2, src: require('./image/2.jpeg')},
{id: 3, src: require('./image/3.jpeg')},
{id: 4, src: require('./image/4.jpeg')},
];
export default class App extends React.Component {
render() {
return (
<ScrollView style={{flex: 1}}>
{images.map(image => {
return (
<TouchableWithoutFeedback key={image.id}>
<Animated.View>
<Image source={image.src} />
</Animated.View>
</TouchableWithoutFeedback>
);
})}
</ScrollView>
);
}
}
Adding Size configurations to Image with Dimensions component
In this step, we are going to configure the height and width of our images on the basis of screen size. In order to get the screen height and width, we are going to make use of Dimensions component provided by the react-native package. Dimensions component provides get() function through which we can get the full-screen window width and height. Here, we are going to store those screen window height and width into two variables namely SCREEN_WIDTH AND SCREEN_HEIGHT as shown in the code snippet below:
Image,
ScrollView,
TouchableWithoutFeedback,
Animated,
Dimensions,
} from 'react-native';
let SCREEN_WIDTH = Dimensions.get('window').width;
let SCREEN_HEIGHT = Dimensions.get('window').height;
Then, we are going to add those size style configurations to our Animated View component with height decreased by 150 as shown in the code snippet below:
<TouchableWithoutFeedback key={image.id}>
<Animated.View
style={{
height: SCREEN_HEIGHT - 150,
width: SCREEN_WIDTH,
padding: 15,
}}>
<Image source={image.src} />
</Animated.View>
</TouchableWithoutFeedback>
Therefore, we get the following result in our emulator screen:
Adding styles to Image
This step is pretty simple. We are just going to add some inline styles to our Image component in order to make it look more appealing. We are going to add the inline styles using style prop as shown in the code snippet below:
<TouchableWithoutFeedback key={image.id}>
<Animated.View
style={{
height: SCREEN_HEIGHT - 150,
width: SCREEN_WIDTH,
padding: 15,
}}>
<Image
source={image.src}
style={{
flex: 1,
height: null,
width: null,
resizeMode: 'cover',
borderRadius: 20,
}}
/>
</Animated.View>
</TouchableWithoutFeedback>
Hence, we get the following result in our emulator screen where images appear more better than before.
But, as we can see, there is an overlay of emulator’s status bar over the app’s image.
So, in order to fix that we are going to add a SafeAreaView container. The function of SafeAreaView component is to render content within the safe area boundaries of a device. So, we are going to wrap the ScrollView component with SafeAreaView component as shown in the code snippet below:
import React from 'react';
import {
Image,
ScrollView,
TouchableWithoutFeedback,
Animated,
Dimensions,
SafeAreaView,
} from 'react-native';const images = [
{id: 1, src: require('./image/1.jpeg')},
{id: 2, src: require('./image/2.jpeg')},
{id: 3, src: require('./image/3.jpeg')},
{id: 4, src: require('./image/4.jpeg')},
];
let SCREEN_WIDTH = Dimensions.get('window').width;
let SCREEN_HEIGHT = Dimensions.get('window').height;
export default class App extends React.Component {
render() {
return (
<SafeAreaView style={{flex: 1}}>
<ScrollView style={{flex: 1}}>
{images.map(image => {
return (
<TouchableWithoutFeedback key={image.id}>
<Animated.View
style={{
height: SCREEN_HEIGHT - 150,
width: SCREEN_WIDTH,
padding: 15,
}}>
<Image
source={image.src}
style={{
flex: 1,
height: null,
width: null,
resizeMode: 'cover',
borderRadius: 20,
}}
/>
</Animated.View>
</TouchableWithoutFeedback>
);
})}
</ScrollView>
</SafeAreaView>
);
}
}
Hence, we get the following result our emulator screen:
Finally, our implementation of React Native Shared Element Transition is successful.
Conclusion
In this first part of the tutorial, we learned how to set up the blank react native application. We also learned how to make use of different components from the react-native package. Moreover, we also got detail guidance of how to set up image UI for Animation and make use of Dimensions, ScrollView and SafeAriaView components. Lastly, we successfully completed our implementation of React Native shared Element transitions.
Credit
content from #1 Apple App of the day Animation by Unsureprogrammer
image from Unsplash
Disclosure
This post includes affiliate links; I may receive compensation if you purchase
products or services from the different links provided in this article.