首页 > 解决方案 > Animate.timing 不适用于 nativeEvent onLayout

问题描述

我正在尝试为向下滑动到实际高度的视图框设置动画。起初,如果 View 的最大高度(即查看所有内容所需的高度)小于 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;

如果我只是将动画设为静态而不运行 onLayout 函数,则动画效果很好。但是我需要得到文本框的高度,所以我知道我需要达到什么高度,因为我是从数据库中提取该文本。当我运行称为 getContentHeight() 的 onLayout 函数时,它要么在 0 和 maxHeight 之间来回跳跃,要么只停留在 0。感谢任何帮助!

标签: javascriptcssreact-nativereact-animations

解决方案


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]) 设置描述


推荐阅读