Search code examples
react-nativereact-animatedreact-native-reanimated

Is there a way to animate the increased size of a View when new children are added?


I’m currently using LayoutAnimation to animate a view when children are added. However, since LayoutAnimation causes everything to be animated, globally, and I can’t easily use built-in Animated library to fit my use-case, I’m wondering if react-native-reanimated is able to help.

Here's a snack of my current solution: https://snack.expo.io/@insats/height-adapation

This is what the result of that looks like:

enter image description here

Is there a way to achieve the same thing without using LayoutAnimation? I've looked through all exampled in react-native-reanimated, and I've read through the docs but I'm still not sure if this is possible to do or how I should get started. I've thought about using Animated to move the item-wrapper out of the viewable area and "scroll" it upwards (using transform translateY) when items are added, but that would require fixed height, which I don't have.


Solution

  • I have 2 approaches that I can suggest out of my mind:

    1. You can configure your LayoutAnimation only when your desired state changed. If you use hooks it would be too easy:

      const [state,setState] = useState([]);
      useEffect(()=>{
         /*rest code*/
         LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
      },[state])
      

      Or if you use class component you can catch your desired state change in componentDidUpdate:

      componentDidUpdate(prevProps,prevState){
         if(prevState.items!==state.items){
             LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
         }
      }
      
    2. You can use onLayout function of view:

      addItem = () => {
         this.setState({
            items: [...this.state.items, {title:'An item',isNew:true}]
         })
      }; 
      renderItems = () => {
         return this.state.items.map((item, index) => {
            let opacity = new Animated.Value(0);
            return (
              <Animated.View onLayout={({nativeEvent})=>{
                 if(this.state.item.isNew){
                    // here you got the height from nativeEvent.layout.height
                    // Then you have to store the height animate height and opacity to its precise value 
                    // PS I used opacity:0 to calculate the height
                   }
                 }} key={index} style={[styles.item,{opacity}>
                <Text>{item.title}</Text>
              </View>
             )
         });
      };
      

    When it comes to react-native-reanimated I regard it as more faster version of react-native's Animated library. So either way you will have to calculate the height!