我正在一个带有部分列表组件的 react 本机应用程序中构建一个视图,它上面还有一个标题,该标题将显示有关列表的聚合数据。滚动时,标题视图应缩小并带有动画。我所有的动画都工作正常,但是使用onEndreached
道具添加无限滚动时会出现问题。当添加新数据或状态/道具更改时,它会跳到列表顶部。
为了使 SectionList 具有动画效果,我使用Animated.createAnimatedComponent
将其包装以创建一个<AnimatedSectionList />
组件。当它被动画包裹时,问题就会出现。
在下面链接的 gif 中,您可以看到当我向下滚动时它会跳到列表顶部。这是状态发生变化并且我们开始获取更多数据的时候。 https://monosnap.com/file/2aH5iPF2XcygEz381bpHW9QGPGHA2Z
我尝试使用getItemLayout
来计算列表大小,因为我读到当 react 不知道列表的高度时,它可能会很跳跃。
我还尝试在使用scrollTo
加载新数据后滚动到某个部分,但这也不起作用。我使用componentDidUpdate
生命周期方法执行此操作,但是当新数据传入时,componentDidUpdate
调用不一致。
这是我的代码。
const DataItem = [
{ name: "test name", value: "testvalue" },
{ name: "test name", value: "testvalue" },
{ name: "test name", value: "testvalue" },
{ name: "test name", value: "testvalue" },
{ name: "test name", value: "testvalue" }
];
const initialSections = [
{ title: "MY DETAILS", data: DataItem },
{ title: "MY COMMUNITY", data: DataItem },
{ title: "MY FAMILY", data: DataItem }
];
const styles = {
item: {
flex: 1,
height: 50,
marginTop: 1,
backgroundColor: "#dddddd"
},
sectionHeader: {
flex: 1,
height: 20,
marginTop: 1,
backgroundColor: "#00ff00"
}
};
class Edit extends Component {
constructor(props) {
super(props);
this.state = {
scrollEnabled: true,
scrollY: new Animated.Value(0),
sections: initialSections,
refreshing: false
};
_renderSectionHeader(section) {
return (
<View style={styles.sectionHeader}>
<Text> {section.title} </Text>
</View>
);
}
_renderItem(item) {
return (
<View style={styles.item}>
<Text>{item.name}</Text>
</View>
);
}
handleStateButton() {
this.setState({ refreshing: true });
}
fetchMoreData() {
this.setState({ refreshing: true });
const newData = [...this.state.sections, ...initialSections];
setTimeout(
function() {
this.setState({ sections: newData, refreshing: false }); }.bind(this),
2000
);
}
render() {
const backgroundScrollY = this.state.scrollY.interpolate({
inputRange: [0, 224],
outputRange: [0, -50],
extrapolate: "clamp"
});
const backgroundScrollHeight = this.state.scrollY.interpolate({
inputRange: [0, 224],
outputRange: [1, 0.75],
extrapolate: "clamp"
});
const listScrollY = this.state.scrollY.interpolate({
inputRange: [0, 224],
outputRange: [0, -10],
extrapolate: "clamp"
});
const infoOpacity = this.state.scrollY.interpolate({
inputRange: [0, 0.5, 150],
outputRange: [1, 1, 0],
extrapolate: "clamp"
});
const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);
return (
<View
style={{
flex: 1,
// alignItems: "flex-start",
flexDirection: "column"
}}
>
<Animated.View
style={[
{
position: "relative",
// flex: 1,
// alignSelf: "flex-start",
top: 0,
minHeight: 200,
height: 300,
backgroundColor: "#ddee99",
border: "1px solid #0000FF",
justifyContent: "center",
alignItems: "center"
},
{ transform: [{ scaleY: backgroundScrollHeight }] }
]}
>
<Animated.Image
source={{
uri:
"https://images.unsplash.com/photo-1558901591-3a5f333830dd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"
}}
style={[
{ position: "absolute", backgroundColor: "#cccccc" },
{ transform: [{ translateY: backgroundScrollY }] }
]}
blurRadius={1.5}
/>
<Text>{this.state.refreshing && `Fetching data`}</Text>
<Button onPress={this.fetchMoreData} title="Get More Data" />
<Button onPress={this.handleStateButton} title="Changing State" />
</Animated.View>
<AnimatedSectionList
ref={ref => (this.sectionListRef = ref)}
bounces={false}
scrollEnabled={this.state.scrollEnabled}
style={[
{ position: "relative" },
{ transform: [{ translateY: listScrollY }] }
]}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
{ listener: this._onScroll.bind(this) }
)}
sections={this.state.sections}
renderSectionHeader={({ section }) =>
this._renderSectionHeader(section)
}
ListHeaderComponent={() => (
<View
style={{
flex: 1,
flexDirection: "row",
alignItems: "center",
height: 40,
backgroundColor: "#ff00ff"
}}
>
<Text>List Header</Text>
</View>
)}
ListFooterComponent={() => (
<View
style={{
flex: 1,
flexDirection: "row",
alignItems: "center",
height: 80,
backgroundColor: "#FF0"
}}
>
<Text>List Footer</Text>
</View>
)}
getItemLayout={this.getItemLayout}
renderItem={({ item }) => this._renderItem(item)}
keyExtractor={(item, index) => index}
stickySectionHeadersEnabled={true}
onEndReachedThreshold={0.75}
onEndReached={d => {
this.fetchMoreData();
}}
/>
</View>
);
}
}
我希望当状态或道具发生变化时,列表将保持在当前滚动位置,但相反,它会跳到顶部,从而破坏了无限滚动的目的。
如果有任何关于解决这个问题的最佳方式的想法,将不胜感激。
我把
const AnimatedSectionList = Animated.createAnimatedComponent(SectionList);
离开班级,不再跳到顶端