首页 文章

React Native:Animate缩小 Headers 的 Headers

提问于
浏览
20

目标

我试图创建一个带有动画缩小 Headers 的视图,其中tabview包含带有滚动内容的标签 . 见图 .

设置

我正在使用带有TabNavigator的react-navigation . Headers 是具有固定高度的组件,当前位于TabNavigator上方 . Headers 一直固定在标签上方占用宝贵的空间 .

尝试过的方法

  • 我已经尝试了Janic Duplessis Blog Post但由于标签我无法让它工作 .

  • 我也尝试用两个ScrollView / FlatList实现它:一个包裹整个视图,一个包裹内容但我无法得到反应原生传播滚动边缘到达 .

所需效果与Google Play商店中的效果相同 .

Mobile Screenshot Google play

2 回答

  • 2

    我设法用 Animated.diffClamp 实现了这个 - 你可以查看代码here . 我写了一篇文章更详细地解释了代码here

    *我正在使用UI组件的原生基础包(以简化UI代码),但无论是否有动画插值/定义都相同 .

    Demo

  • 14

    您可以通过使用 RN-Animated 组件自己控制动画滚动操作来实现此目的 . 这不是你要求的,但它可以轻松地播放以获得正确的结果,你真的只需要使用任何列表视图的 renderScrollComponent 方法捕获同样的东西......所以...这里是一些代码:

    The Code

    constructor(props) {
        super(props);
    
        this.headerHeight = 150;
    
        this.state = {
            scrollY: new Animated.Value(0),
        };
    }
    
    render() {
        return (
            <View style={[
                    styles.container,
                    {
                        width: this.props.display.width,
                        height: this.props.display.height,
                    }
                ]}>
    
                { this.renderScrollView() }
                { this.renderListHeader() }
    
            </View>
        );
    }
    
    
    renderListHeader() {
        return (
            <Animated.View
                style={[
                    styles.headerContainer,
                    {
                        width: this.props.display.width,
                        height: this.state.scrollY.interpolate({
                            inputRange: [0, this.headerHeight],
                            outputRange: [this.headerHeight, this.headerHeight / 2],
                            extrapolate: 'clamp',
                        }),
                    }
                ]}>
    
                <Text style={[bodyFontStyle, styles.testingText]}>
                    I am a test! 
                </Text>
            </Animated.View>
        );
    }
    
    
    renderScrollView() {
        return (
            <Animated.ScrollView
                bounces={false}
                scrollEventThrottle={1}
                showsVerticalScrollIndicator={false}
                showsHorizontalScrollIndicator={false}
                onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }] )}>
    
                <Animated.View
                    style={[
                        styles.innerScrollContainer,
                        {
                            height: 800,
                            width: this.props.display.width,
                            marginTop: this.headerHeight,
                        }
                    ]}>
    
                    <Text style={[bodyFontStyle, styles.innerContainerText]}>
                        Look ma! No Hands!
                    </Text>
                </Animated.View>
            </Animated.ScrollView>
        );
    }
    
    
    const styles = StyleSheet.create({
        container: {
            position: 'relative',
            backgroundColor: 'transparent',
        },
        headerContainer: {
            position: 'absolute',
            top: 0, left: 0,
            overflow: 'hidden',
            backgroundColor: 'green',
       },
       innerScrollContainer: {
            position: 'relative',
            backgroundColor: 'white',
       },
       innerContainerText: { color: 'black' },
       testingText: { color: 'black' },
    });
    

    我相信你已经知道这个代码正在尝试做什么......但是只是因为故障会发生故障 .

    Code Breakdown

    我使用this.props.display.width / height支持向下发送当前设备屏幕宽度/高度的系统级别宽度/高度,但如果您更喜欢使用flex而不是 .

    您不一定需要硬编码或静态标头大小,只需要在类代码中使用它的中心位置(即类级别或JS模块级别) .

    最后,仅仅因为我将滚动数据插入到框的高度,并不意味着你必须这样做 . 在示例中,您显示它看起来更像是您想要向上翻译框而不是缩小它的高度 .

相关问题