Friday, March 17, 2023
HomeReactConstruct a Customized Modal with the Animated API in React Native by...

Construct a Customized Modal with the Animated API in React Native by Aman Mittal


Construct a Customized Modal with the Animated API in React Native

Printed on Jun 13, 2019

•

16 min learn

•

cover_image

Creating a greater consumer expertise is likely one of the most essential points of any software. That is the place animations in cellular functions come into play. Animations are an essential a part of your cellular software.

Fortuitously, for React Native builders, there may be really useful a method to create fascinating consumer experiences. It may be achieved by Animated API. For many use circumstances Animated API gives one of the best use case to design and create fluid animations.

On this tutorial, you will take dive deep in making a customized modal and animated it on a button click on. That is the ultimate outcome we seeking to obtain in a React Native software.

Desk of Contents

🔗

  • Stipulations
  • Setup up Screens
  • Establishing Redux
  • Creating an animated Customized Modal
  • Integrating Customized Modal to HomeScreen
  • Animating HomeScreen
  • Conclusion

Stipulations

🔗

Here’s a full listing of plugins, packages, and instruments that you just’re going to want as a way to observe alongside.

  • Nodejs >= v8.x.x put in together with npm/yarn.
  • watchman, the file change watcher for React Native tasks.
  • Expo CLI >= v2.19.4.

To get began create a brand new undertaking utilizing expo-cli toolchain with the next set of instructions. The primary command will create a brand new undertaking listing. Be sure you are contained in the undertaking when operating the applying in a simulator surroundings or an actual gadget.

expo-cli init rn-animations

cd rn-animations

yarn begin

We’re utilizing yarn to kickstart the app however you’re most welcome to make use of npm or npm scrips or use Expo CLI device command: expo begin. This fashion you may confirm that the undertaking has been created efficiently.

Subsequent step is to put in completely different dependencies or libraries that our little demo undertaking goes to rely. Run the beneath command from a terminal window.

yarn add redux react-redux styled-components @expo/vector-icons

After putting in these dependencies, that is how bundle.json file appears to be like like.

1{

2 "essential": "node_modules/expo/AppEntry.js",

3 "scripts": {

4 "begin": "expo begin",

5 "android": "expo begin --android",

6 "ios": "expo begin --ios",

7 "net": "expo begin --web",

8 "eject": "expo eject"

9 },

10 "dependencies": {

11 "@expo/vector-icons": "^10.0.2",

12 "expo": "^33.0.0",

13 "react": "16.8.3",

14 "react-dom": "^16.8.6",

15 "react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",

16 "react-native-web": "^0.11.4",

17 "react-redux": "^7.0.3",

18 "redux": "^4.0.1",

19 "styled-components": "^4.3.1"

20 },

21 "devDependencies": {

22 "babel-preset-expo": "^5.1.1"

23 },

24 "non-public": true

25}

Setup up Screens

🔗

Create two screens inside a brand new listing known as screens/. One goes to be the house display for the app and the principle UI level. The second display goes to be a traditional display however will behave like a customized modal by way of UI conduct. You’ll be able to title them no matter you want however be sure that to recollect these names.

Right here is the preliminary snippet of screens/HomeScreen.js.

1import React from 'react';

2import styled from 'styled-components';

3

4class HomeScreen extends React.Part {

5 render() {

6 return (

7 <Container>

8 <ButtonText>Open Modal</ButtonText>

9 </Container>

10 );

11 }

12}

13

14const Container = styled.View`

15 flex: 1;

16 justify-content: heart;

17 align-items: heart;

18`;

19

20const ButtonText = styled.Textual content`

21 font-size: 20px;

22 font-weight: 600;

23`;

24

25export default HomeScreen;

The above snippet is utilizing styled-components to outline new UI components utilizing React Native API. For extra info on to learn on learn how to combine styled-components and its benefit in a React Native app, please undergo this hyperlink.

For CustomModal.js:

1import React from 'react';

2import styled from 'styled-components';

3

4class CustomModal extends React.Part {

5 render() {

6 return (

7 <Container>

8 <Textual content>CustomModal</Textual content>

9 </Container>

10 );

11 }

12}

13

14const Container = styled.View`

15 flex: 1;

16 justify-content: heart;

17 align-items: heart;

18`;

19

20const Textual content = styled.Textual content`

21 font-size: 20px;

22 font-weight: 600;

23`;

24

25export default CustomModal;

Now, allow us to import the HomeScreen element inside App.js. This element goes to be the entry level of our app.

1import React from 'react';

2

3import HomeScreen from './screens/HomeScreen';

4

5export default perform App() {

6 return <HomeScreen />;

7}

On operating the applying utilizing yarn begin you’re going to get the next outcome. The header has a breakthrough line signifies that the stack navigator has been built-in into our app.

Establishing Redux

🔗

On this part, allow us to create a easy reducer for Redux state administration library. It may be that redux as a library is overkill for the aim of this tutorial, so if you happen to do not need to use it, please discover a approach that works for you. Additionally, I’m not going to get into particulars of how it is best to handle reducers and actions proper now. That mentioned, first create a reducer inside a brand new file known as reducers/index.js with an preliminary state.

1const initialState = {

2 motion: ''

3};

4

5const reducer = (state = initialState, motion) => {

6 swap (motion.kind) {

7 case 'OPEN_MODAL':

8 return { ...state, motion: 'openModal' };

9 case 'CLOSE_MODAL':

10 return { ...state, motion: 'closeModal' };

11 default:

12 return state;

13 }

14};

15

16export default reducer;

For the reason that redux and react-redux dependencies are already put in, open App.js file and inside write the code to hook a retailer supplier for redux to handle world state within the app.

1import React from 'react';

2import { createStore } from 'redux';

3import { Supplier } from 'react-redux';

4import HomeScreen from './screens/HomeScreen';

5import reducer from './reducers';

6

7const retailer = createStore(reducer);

8

9const App = () => (

10 <Supplier retailer={retailer}>

11 <HomeScreen />

12 </Supplier>

13);

14

15export default App;

The redux setup is full. Allow us to transfer on to the following part the place the actual factor begins.

Creating an animated Customized Modal

🔗

Despite the fact that we’re creating this tradition modal as a display, you may at all times use this as a re-usable element. Open CustomModel.js file and add the next snippet of code.

1import React from 'react';

2import styled from 'styled-components';

3

4class CustomModal extends React.Part {

5 render() {

6 return (

7 <Container>

8 <Header />

9 <Physique />

10 </Container>

11 );

12 }

13}

14

15const Container = styled.View`

16 place: absolute;

17 background: white;

18 width: 100%;

19 peak: 100%;

20 z-index: 100;

21`;

22

23const Header = styled.View`

24 background: #333;

25 peak: 150px;

26`;

27

28const Physique = styled.View`

29 background: #eaeaea;

30 peak: 900px;

31`;

32

33export default CustomModal;

The above element is easy. It comprises three react native views. On the Container we’re utilizing the CSS property place: absolute. The z-index will permit the modal to look on the highest of the HomeScreen element. The Header and the Physique are subviews with fastened peak.

To be able to see this in motion, open HomeScreen.js and import it.

1

2import CustomModal from './CustomModal';

3

4class HomeScreen extends React.Part {

5 render() {

6 return (

7 <Container>

8 <CustomModal />

9 <ButtonText>Open Modal</ButtonText>

10 </Container>

11 );

12 }

13}

14

15

You’re going to get the next lead to your simulator.

Nice! Now that we are able to see the Customized Mannequin on the display, allow us to begin making use of some animations. To use animations on this demo software, we will probably be utilizing Animated API from React Native. You don’t have to put in something reasonably than import the API from React Native core. Open CustomModel.js and modify it. Within the beneath snippet, additionally outline an preliminary state.

This preliminary state worth defines an Animated high worth to push mannequin up and down.

1import React from 'react';

2import styled from 'styled-components';

3import { Animated } from 'react-native';

4

5class CustomModal extends React.Part {

6 state = {

7 high: new Animated.Worth(900)

8 };

9 render() {

10 return (

11 <AnimatedContainer fashion={{ high: this.state.high }}>

12 <Header />

13 <Physique />

14 </AnimatedContainer>

15 );

16 }

17}

18

19const Container = styled.View`

20 place: absolute;

21 background: white;

22 width: 100%;

23 peak: 100%;

24 z-index: 100;

25`;

26

27const AnimatedContainer = Animated.createAnimatedComponent(Container);

28

29const Header = styled.View`

30 background: #333;

31 peak: 150px;

32`;

33

34const Physique = styled.View`

35 background: #eaeaea;

36 peak: 900px;

37`;

38

39export default CustomModal;

Proper now, the preliminary high worth is receiving an Animated worth of 900. The syntax Animated.Worth() is used to bind fashion properties akin to we’re utilizing with AnimatedContainer. To be able to carry out animations, the element or the View needs to be Animated, thus, you may Animated.createAnimatedComponent() to rework a primary View an Animated one.

Subsequent, outline a customized technique known as toggleModal earlier than the render perform. This perform will deal with the animations to open and shut the modal. To date, it’s:

1componentDidMount() {

2 this.toggleModal()

3 }

4

5toggleModal = () => {

6 Animated.spring(this.state.high, {

7 toValue: 174

8 }).begin()

9}

Within the above snippet, we’re utilizing spring animations utilizing Animated.spring() technique. That is used to configure animations primarily based on the analytical values to create a easy spring mannequin primarily based on physics. To learn extra about this technique, check out this hyperlink in official React Native documentation. The toValue is handed because the second parameter. Lastly, to begin an animation, it’s worthwhile to name the tactic .begin().

To set off this animation on the primary render of the element CustomModal, we’re utilizing React’s lifecycle technique componentDidMount().

You’re going to get the next outcome.

We have to add a button to shut the modal. Allow us to add the kinds and examine for the shut button on the modal. Create a CloseView element with styled-components library inside a TouchableOpacity button. Additionally, for the shut icon, we’re going to use @expo/vector-icons library.

1import React from 'react';

2import styled from 'styled-components';

3import { Animated, TouchableOpacity, Dimensions } from 'react-native';

4import * as Icon from '@expo/vector-icons';

5

6const screenHeight = Dimensions.get('window').peak;

7

8class CustomModal extends React.Part {

9 state = {

10 high: new Animated.Worth(screenHeight)

11 };

12

13 componentDidMount() {

14 this.toggleModal();

15 }

16

17 toggleModal = () => {

18 Animated.spring(this.state.high, {

19 toValue: 174

20 }).begin();

21 };

22

23 closeModal = () => {

24 Animated.spring(this.state.high, {

25 toValue: screenHeight

26 }).begin();

27 };

28

29 render() {

30 return (

31 <AnimatedContainer fashion={{ high: this.state.high }}>

32 <Header />

33 <TouchableOpacity

34 onPress={this.closeModal}

35 fashion={{

36 place: 'absolute',

37 high: 120,

38 left: '50%',

39 marginLeft: -22,

40 zIndex: 1

41 }}

42 >

43 <CloseView fashion={{ elevation: 10 }}>

44 <Icon.Ionicons title="ios-close" dimension={44} coloration="blue" />

45 </CloseView>

46 </TouchableOpacity>

47 <Physique />

48 </AnimatedContainer>

49 );

50 }

51}

52

53const Container = styled.View`

54 place: absolute;

55 background: white;

56 width: 100%;

57 peak: 100%;

58 z-index: 100;

59`;

60

61const AnimatedContainer = Animated.createAnimatedComponent(Container);

62

63const Header = styled.View`

64 background: #333;

65 peak: 150px;

66`;

67

68const Physique = styled.View`

69 background: #eaeaea;

70 peak: ${screenHeight};

71`;

72

73const CloseView = styled.View`

74 width: 44px;

75 peak: 44px;

76 border-radius: 22px;

77 background: white;

78 justify-content: heart;

79 align-items: heart;

80 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.5);

81`;

82

83export default CustomModal;

To calculate the peak of a display’s gadget, within the above snippet, begin by importing Dimensions API. React Native makes use of Dots Per Inch (DPI) to measure the dimensions (width and peak) of a tool’s display. Dimensions.get("window").peak permits to collect the display peak. We then use this screenHeight variable in three locations. First, the preliminary state which was earlier than had a static worth of 900 is now capable of adapt for various units.

Second, to shut the modal or inside closeModal() technique. Within the toggleModal perform we’re setting a customized to worth of 174 which leaves a partial view of the HomeScreen within the background. For those who set this worth to 0, the customized modal will cowl the entire display. To shut the modal is setting this worth to default display’s peak. The TouchableOpacity that wraps the shut button invokes the tactic closeModal.

The third place the place the variable screenHeight are the kinds of the view container: Physique. Please word that box-shadow is not going to work on Android units. For those who nonetheless need to give the shut button a shadow, use elevation property as inline kinds to CloseView.

You’re going to get the next lead to your simulator gadget.

Integrating Redux to Modal

🔗

On this part, you will use Redux to handle the state of opening and shutting the modal. We now have already outlined the reducers and actions to serve this goal. Open CustomModal.js and import the join Hight Order Operate react-redux library. After that, create two new features which are considerably boilerplate code when utilizing a redux in any React or React Native software. These features are known as: mapStateToProps() and mapDispatchToProps().

1

2import { join } from 'react-redux';

3

4perform mapStateToProps(state) {

5 return { motion: state.motion };

6}

7

8perform mapDispatchToProps(dispatch) {

9 return {

10 closeModal: () =>

11 dispatch({

12 kind: 'CLOSE_MODAL'

13 })

14 };

15}

16

17export default join(mapStateToProps, mapDispatchToProps)(CustomModal);

Subsequent, allow us to merge the enterprise logic to set off animations for opening and shutting the modal inside the identical toggleModal perform. The beneath snippet makes use of if statements to trace the precise motion coming from the worldwide state.

1toggleModal = () => {

2 if (this.props.motion === 'openModal') {

3 Animated.spring(this.state.high, {

4 toValue: 174

5 }).begin();

6 }

7 if (this.props.motion === 'closeModal') {

8 Animated.spring(this.state.high, {

9 toValue: screenHeight

10 }).begin();

11 }

12};

Additionally, change the worth for onPress attribute on the TouchableOpacity to onPress={this.props.closeMenu}. Lastly, componentDidMount() technique goes to name toggleModal() solely on the preliminary render which suggests it will be known as solely as soon as. To resolve this, allow us to use componentDidUpdate(). This lifecycle technique triggers each time there’s a new state or change in props.

1componentDidUpdate() {

2 this.toggleModal()

3 }

Integrating Customized Modal to HomeScreen

🔗

For the reason that preliminary state on the software degree proper now could be empty, you aren’t going to see the modal set off, by itself, once you refresh the Expo app. This serves the aim of conserving the default conduct of the modal to be closed. However high open this tradition modal, we’re going to add a button on the HomeScreen to activate it.

Open HomeScreen.js and join it to the redux state like beneath.

1import React from 'react';

2import { TouchableOpacity } from 'react-native';

3import styled from 'styled-components';

4import { join } from 'react-redux';

5import CustomModal from './CustomModal';

6

7class HomeScreen extends React.Part {

8 render() {

9 return (

10 <Container>

11 <CustomModal />

12 <TouchableOpacity onPress={this.props.openModal}>

13 <ButtonText>Open Modal</ButtonText>

14 </TouchableOpacity>

15 </Container>

16 );

17 }

18}

19

20const Container = styled.View`

21 flex: 1;

22 justify-content: heart;

23 align-items: heart;

24`;

25

26const ButtonText = styled.Textual content`

27 font-size: 20px;

28 font-weight: 600;

29`;

30

31perform mapStateToProps(state) {

32 return { motion: state.motion };

33}

34

35perform mapDispatchToProps(dispatch) {

36 return {

37 openModal: () =>

38 dispatch({

39 kind: 'OPEN_MODAL'

40 })

41 };

42}

43

44export default join(mapStateToProps, mapDispatchToProps)(HomeScreen);

Click on the button Open Modal on the UI display and you’re going to get related outcomes as follows.

Congratulations! You’ve simply created a customized mannequin that’s animated and built-in it from one other display. You’ll be able to finish this tutorial proper right here if it serves the aim or the because the title suggests. Although, if you wish to proceed, allow us to add some animations to the HomeScreen to create a delightful UI within the subsequent part.

Animating HomeScreen

🔗

Within the HomeScreen element we’re going to import fairly a couple of APIs from React Native. The outcome we try to attain is as follows. It is going to be simpler so that you can view what we need to occur to know the code on this part.

Now that you’ve got seen that allow us first undergo what are we going to import from react-native.

1

2import {

3 TouchableOpacity,

4 StatusBar,

5 Animated,

6 Easing,

7 Platform

8} from 'react-native';

Within the above demo, we’re switching between standing bar’s coloration from darkish to gentle when the modal opens, we’re going to use StatusBar inside componentDidMount().

1 componentDidMount() {

2 StatusBar.setBarStyle("dark-content", true)

3

4 if (Platform.OS == "android") {

5 StatusBar.setBarStyle("light-content", true)

6 }

7 }

Subsequent, we outline an preliminary state to handle Animations with two properties, scale and opacity.

1state = {

2 scale: new Animated.Worth(1),

3 opacity: new Animated.Worth(1)

4};

The create a toggleModal technique the place many of the issues are taking place. It will get triggered by componentDidUpdate() lifecycle technique similar to within the CustomModal element.

1componentDidUpdate() {

2 this.toggleModal()

3 }

4

5 toggleModal = () => {

6 if (this.props.motion === "openModal") {

7 Animated.timing(this.state.scale, {

8 toValue: 0.9,

9 length: 300,

10 easing: Easing.in()

11 }).begin()

12 Animated.spring(this.state.opacity, {

13 toValue: 0.5

14 }).begin()

15

16 StatusBar.setBarStyle("light-content", true)

17 }

18

19 if (this.props.motion === "closeModal") {

20 Animated.timing(this.state.scale, {

21 toValue: 1,

22 length: 300,

23 easing: Easing.in()

24 }).begin()

25 Animated.spring(this.state.opacity, {

26 toValue: 1

27 }).begin()

28

29 StatusBar.setBarStyle("dark-content", true)

30 }

31 }

To set off the impact HomeScreen shrinking within the background when the modal opens, is achieved through the use of Animated.timing(). This technique maps time vary to an easing worth. This easing worth triggers the Easing module from react native core. This module implements widespread visualization motions akin to bounce, elastic, in (which we’re utilizing) and out, cubic, sin, again, ease, linear, quad, inout and lots of extra. To get full details about Easing, please confer with the docs right here.

The Animated.timing() has a default worth of 500 milliseconds. We’re altering it to 300.

To create partial opacity when the house display shrinks within the background, we’re once more utilizing spring animations. Relying on whether or not the modal is being opened or closed, the fashion of the StatusBar is being modified by calling the StatusBar.setBarStyle() technique.

Right here is the entire code for HomeScreen.js file.

1import React from 'react';

2import {

3 TouchableOpacity,

4 StatusBar,

5 Animated,

6 Easing,

7 Platform

8} from 'react-native';

9import styled from 'styled-components';

10import { join } from 'react-redux';

11import CustomModal from './CustomModal';

12

13class HomeScreen extends React.Part {

14 state = {

15 scale: new Animated.Worth(1),

16 opacity: new Animated.Worth(1)

17 };

18

19 componentDidMount() {

20 StatusBar.setBarStyle('dark-content', true);

21

22 if (Platform.OS == 'android') {

23 StatusBar.setBarStyle('light-content', true);

24 }

25 }

26

27 componentDidUpdate() {

28 this.toggleModal();

29 }

30

31 toggleModal = () => {

32 if (this.props.motion === 'openModal') {

33 Animated.timing(this.state.scale, {

34 toValue: 0.9,

35 length: 300,

36 easing: Easing.in()

37 }).begin();

38 Animated.spring(this.state.opacity, {

39 toValue: 0.5

40 }).begin();

41

42 StatusBar.setBarStyle('light-content', true);

43 }

44

45 if (this.props.motion === 'closeModal') {

46 Animated.timing(this.state.scale, {

47 toValue: 1,

48 length: 300,

49 easing: Easing.in()

50 }).begin();

51 Animated.spring(this.state.opacity, {

52 toValue: 1

53 }).begin();

54 StatusBar.setBarStyle('dark-content', true);

55 }

56 };

57

58 render() {

59 return (

60 <RootView>

61 <CustomModal />

62 <AnimatedContainer

63 fashion={{

64 remodel: [{ scale: this.state.scale }],

65 opacity: this.state.opacity

66 }}

67 >

68 <TouchableOpacity onPress={this.props.openModal}>

69 <ButtonText>Open Modal</ButtonText>

70 </TouchableOpacity>

71 </AnimatedContainer>

72 </RootView>

73 );

74 }

75}

76

77const RootView = styled.View`

78 flex: 1;

79 background: black;

80`;

81

82const Container = styled.View`

83 flex: 1;

84 background: white;

85 border-top-left-radius: 10px;

86 border-top-right-radius: 10px;

87 justify-content: heart;

88 align-items: heart;

89`;

90

91const AnimatedContainer = Animated.createAnimatedComponent(Container);

92

93const ButtonText = styled.Textual content`

94 font-size: 20px;

95 font-weight: 600;

96`;

97

98perform mapStateToProps(state) {

99 return { motion: state.motion };

100}

101

102perform mapDispatchToProps(dispatch) {

103 return {

104 openModal: () =>

105 dispatch({

106 kind: 'OPEN_MODAL'

107 })

108 };

109}

110

111export default join(mapStateToProps, mapDispatchToProps)(HomeScreen);

Within the above snippet, do pay attention to RootView. We’re additionally changing the nice outdated Container into an Animated view.

Conclusion

🔗

This completes this tutorial about creating animated customized modal to offer a nice consumer expertise in your react native software. You discovered learn how to use the animated library and a few of its strategies akin to spring, timing together with Easing module. With the assistance of redux to handle state, you created a customized modal UI.


I am a software program developer and a technical author. On this weblog, I write about Technical writing, Node.js, React Native and Expo.

At the moment, working at Expo. Beforehand, I’ve labored as a Developer Advocate, and Senior Content material Developer with corporations like Draftbit, Vercel and Crowdbotics.

RELATED ARTICLES

Most Popular

Recent Comments