0

I'm trying to animate a View box sliding down to it's actual height. At first, if the View's max height, which is the height needed to see all the contents, is less than 70, there is no need for an animation. If the max height is greater than 70, then I set the description height to 70, and when the view is clicked, it will animate towards the max height. This is my goal.

For some reason, I'm having trouble with the onLayout function obtaining the needed content height. Here is my code:

function card() {

    const [expandedDescription, setexpandedDescription] = useState(false);
    const [descriptionHeight, setdescriptionHeight] = useState(new Animated.Value(0))
    const [layoutCount, setlayoutCount] = useState(0)
    const [maxContentHeight, setmaxContentHeight] = useState(0);

    const getContentHeight = (event:any) => {
        setmaxContentHeight(event.nativeEvent.layout.height);
        if(maxContentHeight < 70){
            setdescriptionHeight(new Animated.Value(maxContentHeight));
        }
        else{
            setdescriptionHeight(new Animated.Value(70));
        }
    }

    const toggle = () => {
        console.log(maxContentHeight);
        if(maxContentHeight > 70){
            Animated.timing(descriptionHeight, {
                toValue: expandedDescription ? descriptionHeight : maxContentHeight,
                duration: 300,
            }).start();
            setexpandedDescription(!expandedDescription);
        }
    }

    return (
        <View style={styles.cardContainer}>
            <Animated.View style={[styles.descriptionContainer, {height:descriptionHeight}]} onLayout={(event:any) => getContentHeight(event)} >
                <Text style={styles.descriptionHeaderText}>Description</Text>
                <TouchableOpacity onPress={() => toggle()}>
                    <Text style={styles.descriptionText}>Lorem ipsum dolor sit amet, consectetur 
                        adipiscing elit. Aenean bibendum tincidfffffffffunt libero, nec luctus dolor consequat 
                        quis. Phasellus portalike elephants and had to work hard to earn their while chicken 
                    </Text>
                </TouchableOpacity>
            </Animated.View>
        </View>
    )
}

const styles = StyleSheet.create({
    cardContainer: {
        width: '95%',
        marginBottom: 10,
        backgroundColor: '#ffffff',
        borderRadius:25,
        height: 'auto',
        alignItems:'center',
        paddingLeft: 10,
        paddingRight: 10,
    },
    descriptionContainer:{
        width: '100%',
        alignItems:'center',
        marginTop: 10,
        padding:5
    },
    descriptionHeaderText:{
        fontSize: 15,
        color:'#8E8E8E',
    },
    descriptionText:{
        marginTop: 5,
    },
  });

export default card;

If I just make the animation static and do not run the onLayout function, the animation works perfectly. But I need to get that height of the text box so I know what height I need to get to, since I'm pulling that text from a database. Either when I run the onLayout function, which is called, getContentHeight(), it either jumps back and forth between 0 and the maxHeight, or it just stays at 0. Any help is appreciated!

frankied003
  • 466
  • 6
  • 26

1 Answers1

0

useState is asynchrouninous. try to change this:

const getContentHeight = (event:any) => {
    setmaxContentHeight(event.nativeEvent.layout.height);
    if(maxContentHeight < 70){
        setdescriptionHeight(new Animated.Value(maxContentHeight));
    }
    else{
        setdescriptionHeight(new Animated.Value(70));
    }
}

to this:

const getContentHeight = (event:any) => {
    const height = event.nativeEvent.layout.height;
    setmaxContentHeight(height);
    if(height < 70){
        setdescriptionHeight(new Animated.Value(height));
    }
    else{
        setdescriptionHeight(new Animated.Value(70));
    }
}

In addition, I think onLayout of animated components works differently.

Try changing the onLayout like this:

       <Animated.View
          onLayout={Animated.event([
            {
              nativeEvent: {
                layout: {
                  height: maxContentHeight
                }
              }
            }
          ])}
        />

and then setting the description by using useEffect(() => {...}, [maxContentHeight])

D10S
  • 1,468
  • 2
  • 7
  • 13
  • Thanks for your answer, it makes sense, but no luck. The description height starts at 0 still, its so wack. I console.log(height) within the getContentHeight() function and It didn't print... am i calling the function wrong? Should i just make this whole function async? – frankied003 Jul 09 '20 at 12:17
  • Okay, now it's just saying the height is 10, which is wrong... it should be like over 100. – frankied003 Jul 09 '20 at 12:23
  • At least it fires.. I think that onLayout with animtaed components works different. I edited my answer accordingly. I be glad to know if it works for my self education. – D10S Jul 09 '20 at 12:39