我在KeyboardAvoidingView中有一个FlatList。当键盘显示时,我想滚动到FlatList的末尾。
我正在聆听键盘上的演出'被触发的事件,但由于FlatList在调用scrollToEnd后没有滚动到最后,因此可能会被触发太早。
我已经查看了KeyboardAvoidingView的onLayout事件,但只是设置onLayout事件来触发一个函数似乎阻止了KeyboardAvoidingView在显示键盘时调整它的大小。
<KeyboardAvoidingView behavior='padding' style={{ flex: 1}} onLayout={this._scrollEnd}>
代码:
import React from 'react';
import {Image, Linking, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Button, Alert, FlatList, TextInput, KeyboardAvoidingView, Keyboard} from 'react-native';
import { MonoText } from '../components/StyledText';
export default class HomeScreen extends React.Component {
constructor() {
super();
this.state = {
messages: getMessages()
};
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._scrollEnd);
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidHide', this._scrollEnd);
}
_scrollEnd = (evt) => {
this.refs.flatList1.scrollToEnd();
}
render() {
return (
<KeyboardAvoidingView behavior='padding' style={{ flex: 1}} >
<FlatList
style={{ flex:1}}
ref="flatList1"
data={this.state.messages}
renderItem={({ item }) => <Text>{item.text}</Text>}
/>
</KeyboardAvoidingView>
);
}
}
答案 0 :(得分:25)
我正在制作聊天组件,我想要同样的事情。它是这样的:
#!/Users etc
import re,sys,os.path,pip,os.path
import webbrowser
def press_key(key):
cmd = "osascript -e 'tell application \"System Events\" to keystroke \"" + key + "\"'"
os.system(cmd)
b=webbrowser.get('safari')
b.open('google.com') and press_key("hello")
键盘弹出会触发布局,以便修复。到达的新聊天消息会触发内容更改,因此它也会滚动到底部(这是我想要的聊天窗口)
答案 1 :(得分:20)
实际上如果你总是想滚动到最后,意味着你总是希望看到最新的消息,我是对的吗?
然后使用新版本的react-native。并添加倒置以更改平面列表的倒置。
<FlatList
inverted
style={{ flex:1}}
ref="flatList1"
data={this.state.messages}
renderItem={({ item }) => <Text>{item.text}</Text>}
/>
然后将您的 this.state.messages 重新排列。那么您的最新消息将始终显示在平面列表的底部
就我而言,我不需要使用 KeyboardAvoidingView
答案 2 :(得分:1)
一些用户 (@Nathileo) 要求使用基于钩子的方法滚动到 FlatList 的末尾。
首先,你需要实现 React 的 useRef 钩子:
import {useRef} from 'react';
const yourRef = useRef(null);
其次,FlatList 标签必须配备一个引用和所需的功能:
<FlatList
ref={yourRef}
onContentSizeChange={() => yourRef.current.scrollToEnd() }
onLayout={() => yourRef.current.scrollToEnd() }
/>
答案 3 :(得分:0)
如上文comment所述,getItemLayout
应解决您的问题。
根据Reactive FlatList documentation:
getItemLayout
是一个可选的优化,如果您事先知道项目的高度,我们就可以跳过动态内容的测量。getItemLayout
是最有效的,如果您有固定的高度项,则易于使用,例如:
getItemLayout={(data, index) => (
{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}
如果您使用ItemSeparatorComponent
,请不要忘记在计算结果偏移量时合并分隔符的高度或宽度。
答案 4 :(得分:0)
我一直在使用这个用键盘管理平板高度的小组件。这使用了renderProps模式,因此您可以重用它:)
import { PureComponent } from 'react';
import { Keyboard, Dimensions, Animated } from 'react-native';
const DURATION = 200;
class ListSpacer extends PureComponent {
state = {
screenHeight: Dimensions.get('window').height,
flatListHeight: new Animated.Value(Dimensions.get('window').height),
};
componentDidMount() {
this._keyboardDidShowListener = Keyboard.addListener(
'keyboardDidShow',
this._keyBoardDidShow,
);
this._keyboardDidHideListener = Keyboard.addListener(
'keyboardDidHide',
this._keyBoardDidHide,
);
}
componentWillUnmount() {
this._keyboardDidShowListener.remove();
this._keyboardDidHideListener.remove();
}
_keyBoardDidShow = e => {
Animated.timing(this.state.flatListHeight, {
toValue: Dimensions.get('window').height - e.endCoordinates.height,
duration: DURATION,
}).start();
};
_keyBoardDidHide = () => {
Animated.timing(this.state.flatListHeight, {
toValue: Dimensions.get('window').height,
duration: DURATION,
}).start();
};
render() {
const renderProps = {
flatListHeight: this.state.flatListHeight,
};
if (this.props.children) {
return this.props.children(renderProps);
}
return this.props.render(renderProps);
}
}
export default ListSpacer;
我们在这里听键盘事件,并且endcoordinates给你键盘高度。这样你就可以用它来制作平面列表高度。
import {
FlatList,
KeyboardAvoidingView,
Animated,
} from 'react-native';
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
return (
<ListSpacer>
{({ flatListHeight }) => (
<KeyboardAvoidingView
behavior="padding"
keyboardVerticalOffset={INPUT_HEIGHT}
>
<AnimatedFlatList
inverted
style={{ height: flatListHeight }}
data={data.comments}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
contentContainerStyle={styles.contentList}
/>
</KeyboardAvoidingView>
)}
</ListSpacer>
);
在这里,我有这个教程,我展示了如果你更具视觉效果:)