React native Onscroll本机事件更新所有相同类型的包装器组件
我在react导航库中使用了一个包装器平面列表组件。 此组件位于不同的stacknavigation选项卡中,用于处理标题的动画React native Onscroll本机事件更新所有相同类型的包装器组件,react-native,react-navigation,expo,React Native,React Navigation,Expo,我在react导航库中使用了一个包装器平面列表组件。 此组件位于不同的stacknavigation选项卡中,用于处理标题的动画 import React, { Component } from "react"; import { Constants } from 'expo'; // import PropTypes from "prop-types"; import { Animated, Dimensions, // PanResponder, // Platform,
import React, { Component } from "react";
import { Constants } from 'expo';
// import PropTypes from "prop-types";
import {
Animated,
Dimensions,
// PanResponder,
// Platform,
// ScrollView,
StyleSheet,
FlatList,
// ScrollView,
// StatusBar,
// Text,
// TouchableWithoutFeedback,
// View
} from "react-native";
// import Icon from "react-native-vector-icons/Ionicons";
// Get screen dimensions
const { width, height } = Dimensions.get("window");
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const HEADER_HEIGHT= 40;
const FILTER_HEIGHT= 50;
const STATUS_BAR_HEIGHT = Constants.statusBarHeight;
const NAVBAR_HEIGHT = HEADER_HEIGHT+FILTER_HEIGHT-2;
const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);
export default class AnimatedFlatListComp extends React.PureComponent {
// Define state
state = {
scrollAnim,
offsetAnim,
clampedScroll: Animated.diffClamp(
Animated.add(
scrollAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
}),
offsetAnim,
),
0,
// NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
HEADER_HEIGHT //i mede this one cuz the code abode not work is the value 40
),
};
componentWillUnmount() {
console.log('smontoooo');
// this._isMounted = false;
// Don't forget to remove the listeners!
// this.state.scrollAnim.removeAllListeners();
// this.state.offsetAnim.removeAllListeners();
this._disableListener();
}
componentDidMount() {
this._clampedScrollValue = 0;
this._offsetValue = 0;
this._scrollValue = 0;
this._enableLister()
this._handleScroll()
}
_onMomentumScrollBegin = () => {
console.log('_onMomentumScrollBegin');
clearTimeout(this._scrollEndTimer);
}
_onScrollEndDrag = () => {
this._scrollEndTimer = setTimeout(this._onMomentumScrollEnd, 250);
}
_onMomentumScrollEnd = () => {
console.log('_onMomentumScrollEnd');
console.log(this._scrollValue, NAVBAR_HEIGHT, this._clampedScrollValue, (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2);
const toValue = this._scrollValue > NAVBAR_HEIGHT &&
this._clampedScrollValue > (NAVBAR_HEIGHT - STATUS_BAR_HEIGHT) / 2
? this._offsetValue + NAVBAR_HEIGHT
: this._offsetValue - NAVBAR_HEIGHT;
Animated.timing(this.state.offsetAnim, {
toValue,
duration: 350,
useNativeDriver: true,
}).start();
}
_handleScroll = () => this.props._handleScroll(this.state.clampedScroll)
// _handleScroll = event => {
// const { y } = event.nativeEvent.contentOffset;
// // // console.log(y);
// this.setState({ scrollOffset: y }, () => {
// this.props._handleScroll(this.state.clampedScroll)
// });
//
// };
_scrollToTop = () => {
console.log('_scrollToTop');
if (!!this.flatListRef) {
// this.flatListRef.getNode().scrollTo({ y: 0, animated: true });
this.flatListRef.getNode().scrollToOffset({ offset: 0, animated: true });
}
};
_enableLister = () => {
// this._firstMountFunction();
this.state.scrollAnim.addListener(({ value }) => {
// This is the same calculations that diffClamp does.
const diff = value - this._scrollValue;
this._scrollValue = value;
this._clampedScrollValue = Math.min(
Math.max(this._clampedScrollValue + diff, 0),
NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
);
});
this.state.offsetAnim.addListener(({ value }) => {
this._offsetValue = value;
});
}
_disableListener = () => {
this.state.scrollAnim.removeAllListeners();
this.state.offsetAnim.removeAllListeners();
}
_keyExtractor = (item, index) => index.toString();
// _onScroll = event => {
//
// }
render() {
return (
<AnimatedFlatList
{...this.props}
ref={(ref) => { this.flatListRef = ref; }}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollAnim}}}],
{
useNativeDriver: true,
// listener: this._handleScroll
},
)}
// onScroll={this._onScroll}
removeClippedSubviews={true}
keyExtractor={this._keyExtractor}
onMomentumScrollBegin={this._onMomentumScrollBegin}
onMomentumScrollEnd={this._onMomentumScrollEnd}
onScrollEndDrag={this._onScrollEndDrag}
scrollEventThrottle={1}
/>
);
}
}
import React,{Component}来自“React”;
从“expo”导入{Constants};
//从“道具类型”导入道具类型;
进口{
有生气的
尺寸,
//应答器,
//平台,
//滚动视图,
样式表,
平面列表,
//滚动视图,
//状态栏,
//文本,
//可触摸且无反馈,
//看法
}从“反应本族语”;
//从“反应本机矢量图标/离子图标”导入图标;
//获取屏幕尺寸
const{width,height}=Dimensions.get(“窗口”);
const AnimatedFlatList=Animated.createAnimatedComponent(FlatList);
const HEADER_HEIGHT=40;
常数过滤器高度=50;
const STATUS\u BAR\u HEIGHT=常数.statusBarHeight;
常量导航栏高度=收割台高度+过滤器高度-2;
const scrollAnim=新的动画值(0);
const offsetAnim=新的动画值(0);
导出默认类AnimatedFlatListComp扩展React.PureComponent{
//定义状态
状态={
卷轴动画,
抵消,
clampedScroll:已设置动画的.diffClamp(
动画。添加(
滚动动画({
输入范围:[0,1],
outputRange:[0,1],
外推ELEFT:“夹具”,
}),
抵消,
),
0,
//导航栏高度-状态栏高度,
页眉\u高度//我之所以选择此项,是因为代码abod not work的值为40
),
};
组件将卸载(){
console.log('smontooo');
//这个。_isMounted=false;
//别忘了删除侦听器!
//this.state.scrollAnim.removeAllListeners();
//this.state.offsetAnim.removeAllListeners();
这个。_disableListener();
}
componentDidMount(){
该值为0;
该值为0;
该值为0;
这个。_enableLister()
这个。_handleScroll()
}
_onMomentumScrollBegin=()=>{
console.log(“onMomentumScrollBegin”);
clearTimeout(此.\u scrollEndTimer);
}
_onScrollEndDrag=()=>{
this.\u scrollEndTimer=setTimeout(this.\u onMomentumScrollEnd,250);
}
_onMomentumScrollEnd=()=>{
console.log(“onMomentumScrollEnd”);
console.log(this.\u scrollValue,NAVBAR\u HEIGHT,this.\u clampedScrollValue,(NAVBAR\u HEIGHT-STATUS\u BAR\u HEIGHT)/2);
const toValue=此值。\滚动值>导航栏\高度&&
此._clampedScrollValue>(导航栏高度-状态栏高度)/2
?这是偏移值+导航栏高度
:此._offsetValue-导航栏_高度;
动画。计时(this.state.offsetAnim{
toValue,
持续时间:350,
useNativeDriver:没错,
}).start();
}
_handleScroll=()=>this.props.\u handleScroll(this.state.clampedScroll)
//\u handleScroll=事件=>{
//const{y}=event.nativeEvent.contentOffset;
/////console.log(y);
//this.setState({scrollOffset:y},()=>{
//this.props.\u handleScroll(this.state.clampedScroll)
// });
//
// };
_scrollToTop=()=>{
console.log(“滚动到顶部”);
如果(!!this.flatListRef){
//this.flatListRef.getNode().scrollTo({y:0,动画:true});
this.flatListRef.getNode().scrollToOffset({offset:0,animated:true});
}
};
_enableLister=()=>{
//此函数为;
this.state.scrollAnim.addListener(({value})=>{
//这与diffClamp的计算相同。
const diff=值-此值;
这个。_scrollValue=value;
这是。_clampedScrollValue=Math.min(
最大值(这个值+diff,0),
导航栏高度-状态栏高度,
);
});
this.state.offsetAnim.addListener(({value})=>{
该值为._offsetValue=value;
});
}
_disableListener=()=>{
this.state.scrollAnim.removeAllListeners();
this.state.offsetAnim.removeAllListeners();
}
_keyExtractor=(项,索引)=>index.toString();
//\u onScroll=事件=>{
//
// }
render(){
返回(
{this.flatListRef=ref;}}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[{nativeEvent:{contentOffset:{y:this.state.scrollAnim}}],
{
useNativeDriver:没错,
//听众:这个
},
)}
//onScroll={this.\u onScroll}
RemoveClippedSubview={true}
keyExtractor={this.\u keyExtractor}
onMomentumScrollBegin={this.\u onMomentumScrollBegin}
onMomentumScrollEnd={this.\u onMomentumScrollEnd}
onScrollEndDrag={this.\u onScrollEndDrag}
scrollEventThrottle={1}
/>
);
}
}
这是家长
_handleScroll = clampedScroll => this.setState({ clampedScroll: clampedScroll })
render(){
const { clampedScroll } = this.state;
//
const navbarTranslate = clampedScroll.interpolate({
inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
outputRange: [0, -(NAVBAR_HEIGHT - STATUS_BAR_HEIGHT)],
extrapolate: 'clamp',
});
return (
<AnimatedFlatList
// debug={true}
ref={(ref) => { this.flatListRef = ref; }}
maxToRenderPerBatch={4}
contentContainerStyle={{
paddingTop: NAVBAR_HEIGHT+STATUS_BAR_HEIGHT,
}}
data={this.state.dataSource}
renderItem={
({item, index}) =>
<CardAgenda
item={JSON.parse(item.JSON)}
ChangeSelectedEvent={this.ChangeSelectedEvent}
colorTrail={JSON.parse(item.colorTrail)}
// _sendBackdata={this._getChildrenCategoryData}
searchData={JSON.parse(item.searchData)}
NumAncillary={item.NumAncillary}
indexItinerary={item.id}
index={index}
/>
}
ListEmptyComponent={this._emptyList}
ItemSeparatorComponent={() => <View style={{width: width-40, backgroundColor: 'rgba(0,0,0,0.1)', height: 1, marginTop: 20, marginLeft: 20, marginRight: 20}}/>}
_handleScroll={this._handleScroll}
/>
)}
\u handleScroll=clampedcoll=>this.setState({clampedcoll:clampedcoll})
render(){
const{clampedcoll}=this.state;
//
const navbarTranslate=clampedcoll.interpolate({
输入范围:[0,导航栏高度-状态栏高度],
输出范围:[0,-(导航栏高度-状态栏高度)],
外推:“夹具”,
});
返回(
{this.flatListRef=ref;}}
maxToRenderPerBatch={4}
内容容器样式={{
paddingTop:导航栏高度+状态栏高度,
}}
data={this.state.dataSource}
伦德雷特={
({item,index})=>
}
ListMPtyComponent={this.\u emptyList}
ItemSeparatorComponent={()=>}
_handleScroll={this.\u handleScroll}
/>
)}
其工作正常,但onscroll事件会触发所有包装器的this.state.scrollAnim变量。
我的意思是,如果我向上滚动第一个动画平面列表,标题会向上滚动,但新导航页面中的另一个标题也会向上滚动
正确的行为必须是所有标题必须独立于自己的平面列表
提前感谢这是因为您正在设置对sta的引用
const scrollAnim = new Animated.Value(0);
const offsetAnim = new Animated.Value(0);
export default class AnimatedFlatListComp extends React.PureComponent {
constructor(props){
super(props);
this.scrollAnim = new Animated.Value(0);
this.offsetAnim = new Animated.Value(0);
// Define state
state = {
scrollAnim: this.scrollAnim,
offsetAnim: this.offsetAnim,
clampedScroll: Animated.diffClamp(
Animated.add(
this.scrollAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
}),
this.offsetAnim,
),
0,
// NAVBAR_HEIGHT - STATUS_BAR_HEIGHT,
HEADER_HEIGHT //i mede this one cuz the code abode not work is
the value 40
),
};
}