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
轉載請著名出處!謝謝~~
