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
转载请著名出处!谢谢~~