Hi Guys, Welcome again in another very interesting tutorial of React native and this is Animated Accordion Panels and Ya I know you heard about Accordion Panels in HTML. It’s very basic, commonly used control in HTML but today, I am going to create same Animated Accordion Panels in react native and believe me You will enjoy it.
In brief, what I am doing in Animated Accordion Panels using Layout Animation tutorial?
- First of all, I will create two components( Accordion and App in my case ), First one defines the Accordion panel and another one is used to render that Accordion panel multiple times with different data for each panel.
- And on click on Panel header expand the panel body with nice Layout Animation.
So, let’s get started…
Step – 1: As usual, Import all required components from react , react-native packages.
import React, { Component } from 'react'; import { Text, View, StyleSheet, LayoutAnimation, Platform, UIManager, TouchableOpacity, ScrollView } from 'react-native';
Implement Code for Accordion Component:
Step – 2: Implement constructor method.
constructor() { super(); this.state = { modifiedHeight: 0 } }
Step – 3: Implement componentWillReceiveProps method..
componentWillReceiveProps( nextProps ) { if( nextProps.item.expanded ) { this.setState(() => { return { modifiedHeight: null } }); } else { this.setState(() => { return { modifiedHeight: 0 } }); } }
Explanation:
- componentWillReceiveProps method is a react component life cycle method and is used to notify that new Props are received for this component in which componentWillReceiveProps method is implemented.
- So in this method, I am checking the new received expanded prop value and if it’s true then set null to the modifiedState variable in order to Expand the Panel or if it’s false then set 0 to modifiedState variable in order to Collapse the panel.
Step – 4: Implement shouldComponentUpdate method.
shouldComponentUpdate(nextProps, nextState) { if(nextProps.item.expanded !== this.props.item.expanded) { return true; } return false; }
Explanation:
- This is the very important and powerful method of react component life cycle.
- Basically, shouldComponentUpdate life cycle method is used to improve the performance of react / react native app.
- This method always return a Boolean value (true / false). By default, behind the scenes this method always return true and it’s OK in most of the cases but sometimes and in some cases such as If our have app thousands of items such as in this tutorial I am using 100 items in ScrollView component then always returning true may harm your app performance. So, comment out the shouldComponentUpdate method, re-run the code, see the difference and let me know through comments, what you feel about your app performance before and after applying the shouldComponentUpdate method. I will make a complete detailed tutorial on shouldComponentUpdate life cycle method, so stay in touch.
Step – 5: Implement render method.
render() { return( <View style = { styles.btnTextHolder }> <TouchableOpacity activeOpacity = { 0.8 } onPress = { this.props.onClick } style = { styles.Btn }> <Text style = { styles.btnText }>{ this.props.item.title } </Text> </TouchableOpacity> <View style = {{ height: this.state.modifiedHeight, overflow: 'hidden' }}> <Text style = { styles.text }> { this.props.item.body } </Text> </View> </View> ); }
Implement Code for App Component:
Step – 6: Implement constructor method.
constructor() { super(); if( Platform.OS === 'android' ) { UIManager.setLayoutAnimationEnabledExperimental( true ) } const array = []; for (let i = 1; i <= 100; i++) { array.push({ expanded: false, title: 'Accordian ' + i, body: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." }); } this.state = { AccordionData: [...array] } }
Step – 7: Implement changeLayout method.
changeLayout = ( index ) => { LayoutAnimation.configureNext( LayoutAnimation.Presets.easeInEaseOut ); const array = this.state.AccordionData.map(( item ) => { const newItem = Object.assign({}, item); newItem.expanded = false; return newItem; }); array[index].expanded = true; this.setState(() => { return { AccordionData: array } }); }
Step – 8: Implement render method.
render() { return( <View style = { styles.container }> <ScrollView contentContainerStyle = {{ paddingHorizontal: 10, paddingVertical: 5 }}> { this.state.AccordionData.map(( item, key ) => ( <Accordion key = { key } onClick = { this.changeLayout.bind( this, key ) } item = { item } /> )) } </ScrollView> </View> ); }
Step – 9: Implement custom styles for all required components.
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: (Platform.OS === 'ios') ? 20 : 0 }, text: { fontSize: 17, color: 'black', padding: 10 }, btnText: { textAlign: 'center', color: 'white', fontSize: 20 }, btnTextHolder: { borderWidth: 1, borderColor: 'rgba(0,0,0,0.5)', marginVertical: 5 }, Btn: { padding: 10, backgroundColor: 'rgba(0,0,0,0.5)' } });
Complete Source Code:
import React, { Component } from 'react'; import { Text, View, StyleSheet, LayoutAnimation, Platform, UIManager, TouchableOpacity, ScrollView } from 'react-native'; class Accordion extends Component { constructor() { super(); this.state = { modifiedHeight: 0 } } componentWillReceiveProps( nextProps ) { if( nextProps.item.expanded ) { this.setState(() => { return { modifiedHeight: null } }); } else { this.setState(() => { return { modifiedHeight: 0 } }); } } shouldComponentUpdate(nextProps, nextState) { if(nextProps.item.expanded !== this.props.item.expanded) { return true; } return false; } render() { return( <View style = { styles.btnTextHolder }> <TouchableOpacity activeOpacity = { 0.8 } onPress = { this.props.onClick } style = { styles.Btn }> <Text style = { styles.btnText }>{ this.props.item.title } </Text> </TouchableOpacity> <View style = {{ height: this.state.modifiedHeight, overflow: 'hidden' }}> <Text style = { styles.text }> { this.props.item.body } </Text> </View> </View> ); } } export default class App extends Component { constructor() { super(); if( Platform.OS === 'android' ) { UIManager.setLayoutAnimationEnabledExperimental( true ) } const array = []; for (let i = 1; i <= 100; i++) { array.push({ expanded: false, title: 'Accordian ' + i, body: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." }); } this.state = { AccordionData: [...array] } } changeLayout = ( index ) => { LayoutAnimation.configureNext( LayoutAnimation.Presets.easeInEaseOut ); const array = this.state.AccordionData.map(( item ) => { const newItem = Object.assign({}, item); newItem.expanded = false; return newItem; }); array[index].expanded = true; this.setState(() => { return { AccordionData: array } }); } render() { return( <View style = { styles.container }> <ScrollView contentContainerStyle = {{ paddingHorizontal: 10, paddingVertical: 5 }}> { this.state.AccordionData.map(( item, key ) => ( <Accordion key = { key } onClick = { this.changeLayout.bind( this, key ) } item = { item } /> )) } </ScrollView> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: (Platform.OS === 'ios') ? 20 : 0 }, text: { fontSize: 17, color: 'black', padding: 10 }, btnText: { textAlign: 'center', color: 'white', fontSize: 20 }, btnTextHolder: { borderWidth: 1, borderColor: 'rgba(0,0,0,0.5)', marginVertical: 5 }, Btn: { padding: 10, backgroundColor: 'rgba(0,0,0,0.5)' } });
Enjoy Guys and have fun…