我正在使用倒置的Flatlist
构建聊天应用程序。当调用onEndReached
时,我将新项目添加到列表的顶部,并且一切正常。
问题在于,如果将项目添加到底部,它将立即滚动到列表的底部。这意味着用户必须向上滚动才能阅读刚刚添加的消息(这很糟糕)。
我尝试在scrollToOffset
中调用onContentSizeChange
,但这有一秒的延迟,滚动会来回跳转。
通过在屏幕上保留相同的消息而不是显示新的消息,如何使列表的行为以相同的方式在顶部和底部添加?
答案 0 :(得分:2)
这是演示:https://snack.expo.io/@nomi9995/flatlisttest
解决方案1:
使用maintainVisibleContentPosition道具来防止IOS中的自动滚动,但不幸的是,它在android上不起作用。
<FlatList
ref={(ref) => { this.chatFlatList = ref; }}
style={styles.flatList}
data={this.state.items}
renderItem={this._renderItem}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
}}
/>
解决方案2:
我找到了另一种解决方法,即使用onScroll保留最新的y偏移量,并使用onContentSizeChange添加新项目前后保存内容高度,并计算内容高度的差,然后将新的y偏移量设置为最新的y偏移量+内容高度差!
答案 1 :(得分:0)
您是否尝试过使用keyExtractor? 这可能有助于避免重新渲染,因此请尝试为每个项目使用唯一键。 您可以在这里了解更多信息:https://reactnative.dev/docs/flatlist#keyextractor
答案 2 :(得分:0)
在这里,我要在倒置的平面列表的顶部和底部添加一个新项目。
我希望您可以将您的要求与提供的示例代码进行比较:)
import React, {Component} from 'react';
import {
SafeAreaView,
View,
FlatList,
StyleSheet,
Text,
Button,
Platform,
UIManager,
LayoutAnimation,
} from 'react-native';
if (Platform.OS === 'android') {
if (UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
const getRandomColor = () => {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
};
const DATA = [
getRandomColor(),
getRandomColor(),
getRandomColor(),
getRandomColor(),
getRandomColor(),
];
export default class App extends Component {
scrollValue = 0;
append = true;
state = {
data: DATA,
};
addItem = (top) => {
const {data} = this.state;
let newData;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (top) {
newData = [...data, getRandomColor()];
this.setState({data: newData});
} else {
newData = [getRandomColor(), ...data];
this.setState({data: newData});
}
};
shouldComponentUpdate() {
return this.scrollValue === 0 || this.append;
}
onScrollBeginDrag = () => {
this.append = true;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({});
};
render() {
const {data} = this.state;
return (
<SafeAreaView style={styles.container}>
<Button title="ADD ON TOP" onPress={() => this.addItem(true)} />
<FlatList
data={data}
onScrollBeginDrag={this.onScrollBeginDrag}
renderItem={({item}) => <Item item={item} />}
keyExtractor={(item) => item}
inverted
onScroll={(e) => {
this.append = false;
this.scrollValue = e.nativeEvent.contentOffset.y;
}}
/>
<Button title="ADD ON BOTTOM" onPress={() => this.addItem(false)} />
</SafeAreaView>
);
}
}
function Item({item}) {
return (
<View style={[styles.item, {backgroundColor: item}]}>
<Text style={styles.title}>{item}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
height: 100,
},
title: {
fontSize: 32,
},
});