Animate.timing не работает с nativeEvent onLayout - PullRequest
0 голосов
/ 09 июля 2020

Я пытаюсь анимировать окно просмотра, скользящее вниз до фактической высоты. Во-первых, если максимальная высота представления, то есть высота, необходимая для просмотра всего содержимого, меньше 70, в анимации нет необходимости. Если максимальная высота больше 70, то я устанавливаю высоту описания равной 70, и при щелчке по представлению оно будет анимироваться в сторону максимальной высоты. Это моя цель.

По какой-то причине у меня возникли проблемы с функцией onLayout с получением необходимой высоты содержимого. Вот мой код:

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;

Если я просто сделаю анимацию stati c и не запустил функцию onLayout, анимация будет работать отлично. Но мне нужно получить эту высоту текстового поля, чтобы я знал, до какой высоты мне нужно добраться, поскольку я беру этот текст из базы данных. Либо когда я запускаю функцию onLayout, которая называется getContentHeight (), она либо перескакивает назад и вперед между 0 и maxHeight, либо просто остается на 0. Любая помощь приветствуется!

1 Ответ

0 голосов
/ 09 июля 2020

useState асинхронен. попробуйте изменить это:

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

на это:

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));
    }
}

Кроме того, я думаю, что onLayout анимированных компонентов работает иначе.

Попробуйте изменить onLayout следующим образом :

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

, а затем установите описание с помощью useEffect (() => {...}, [maxContentHeight])

...