[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

轉載請著名出處!謝謝~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM