zoukankan      html  css  js  c++  java
  • [RN] React Native 头部 滑动吸顶效果的实现

     React Native 头部 滑动吸顶效果的实现

    效果如下图所示:

     

    实现方法:

    一、吸顶组件封装

    StickyHeader .js
    import * as React from 'react';
    import {StyleSheet, Animated} from "react-native";
    
    /**
     * 滑动吸顶效果组件
     * @export
     * @class StickyHeader
     */
    export default class StickyHeader extends React.Component {
    
        static defaultProps = {
            stickyHeaderY: -1,
            stickyScrollY: new Animated.Value(0),
        };
    
        constructor(props) {
            super(props);
            this.state = {
                stickyLayoutY: 0,
            };
        }
    
        // 兼容代码,防止没有传头部高度
        _onLayout = (event) => {
            this.setState({
                stickyLayoutY: event.nativeEvent.layout.y,
            });
        };
    
        render() {
            const {stickyHeaderY, stickyScrollY, children, style} = this.props;
            const {stickyLayoutY} = this.state;
            let y = stickyHeaderY !== -1 ? stickyHeaderY : stickyLayoutY;
            const translateY = stickyScrollY.interpolate({
                inputRange: [-1, 0, y, y + 1],
                outputRange: [0, 0, 0, 1],
            });
    
            return (
                <Animated.View
                    onLayout={this._onLayout}
                    style={
                        [
                            style,
                            styles.container,
                            {transform: [{translateY}]}
                        ]}
                >
    
                    {children}
    
                </Animated.View>
            )
        }
    }
    
    const styles = StyleSheet.create({
        container: {
            zIndex: 100
        },
    });

    二、使用

    import React, {Component} from 'react';
    import {Animated, FlatList, Text, View, StyleSheet} from 'react-native';
    import StickyHeader from "./StickyHeader";
    
    export default class MovieListScreen extends Component {
    
        constructor(props) {
            super(props);
            this.state = {
                movieList: [1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8],
    
                scrollY: new Animated.Value(0),
                headHeight: -1
            };
        }
    
        _keyExtractor = (item, index) => index.toString();
    
        _itemDivide = () => {
            return <View style={{height: 1, backgroundColor: '#ccc'}}/>;
        };
    
        render() {
            return (
                <Animated.ScrollView
                    style={{flex: 1}}
                    onScroll={
                        Animated.event(
                            [{
                                nativeEvent: {contentOffset: {y: this.state.scrollY}} // 记录滑动距离
                            }],
                            {useNativeDriver: true}) // 使用原生动画驱动
                    }
                    scrollEventThrottle={1}
                >
    
                    <View onLayout={(e) => {
                        let {height} = e.nativeEvent.layout;
                        this.setState({headHeight: height}); // 给头部高度赋值
                    }}>
                        <View>
                            <Text style={styles.topHeader}>这是头部</Text>
                        </View>
                    </View>
    
                    <StickyHeader
                        stickyHeaderY={this.state.headHeight} // 把头部高度传入
                        stickyScrollY={this.state.scrollY}  // 把滑动距离传入
                    >
                        <View>
                            <Text style={styles.tab}>这是顶部</Text>
                        </View>
                    </StickyHeader>
    
                    <FlatList
                        data={this.state.movieList}
                        renderItem={this._renderItem}
                        keyExtractor={this._keyExtractor}
                        ItemSeparatorComponent={this._itemDivide}
                    />
    
                </Animated.ScrollView>
    
            )
        }
    
        _renderItem = (item) => {
            return (
                <View>
                    <Text style={{height: 200}}>666</Text>
                </View>
            );
        };
    
    }
    
    const styles = StyleSheet.create({
        container: {
            flex: 1,
        },
        topHeader: {
            height: 60,
            textAlign: "center",
        },
        tab: {
            height: 80,
            zIndex: 999,
            textAlign: "center",
            backgroundColor: "red"
        }
    });

    参考:

    https://www.jb51.net/article/162381.htm

    本博客地址: wukong1688

    本文原文地址:https://www.cnblogs.com/wukong1688/p/11045306.html

    转载请著名出处!谢谢~~

  • 相关阅读:
    vertical-align:middle 垂直居中无效的原因
    meta标签的使用
    异常重试框架Spring Retry实践
    springboot 整合retry(重试机制)
    Centos7-Docker1.12开启守护进程(远程调用)
    Centos7安装docker与docker-compose
    Centos 下 Jenkins2.6 + Git + Maven Shell一件部署与备份
    Docker实战
    利用 Nginx 实现限流
    Feign拦截器应用 (F版)
  • 原文地址:https://www.cnblogs.com/wukong1688/p/11045306.html
Copyright © 2011-2022 走看看