我正在用本地本机构建聊天UI,并且在ScrollView中使用KeyboardAvoidingView时遇到问题。选择TextInput时,输入字段和键盘之间的高度似乎根据我使用的设备而有所不同。如何对此进行标准化,以使其在所有设备上均能正常工作?
import React from 'react'
import { StyleSheet, View, Text, TextInput, ScrollView, KeyboardAvoidingView, Platform } from 'react-native'
import Message from './message'
export default class Messages extends React.Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: 'Messages',
headerStyle: {
backgroundColor: 'rgb(0,0,0)',
},
headerTitleStyle: {
fontSize: 20,
color: 'rgb(255,255,255)'
},
headerTintColor: 'rgb(0,122,255)',
})
state = {
messages: [
{
message: 'yeah its not working',
userId: 1,
userName: 'Client'
},
{
message: 'what isnt working...',
userId: 2,
userName: 'Sean'
},
{
message: 'it, all of it',
userId: 1,
userName: 'Client'
},
{
message: 'were on it',
userId: 3,
userName: 'Matt'
},
{
message: 'fjdklsajfklsdjafkdjslkafjkdsjal;fdks;lajfdklsjldjskfja;sfjasdfjasdjlkfaj',
userId: 3,
userName: 'Matt'
},
{
message: 'great!',
userId: 1,
userName: 'Client'
},
{
message: 'blah',
userId: 1,
userName: 'Client'
},
{
message: 'derp',
userId: 2,
userName: 'Sean'
},
{
message: 'merh!',
userId: 2,
userName: 'Sean'
},
{
message: 'help pls',
userId: 2,
userName: 'Sean'
},
]
}
renderMessages = (messages) => {
return messages.map((data, i) => <Message data={data} key={i}/>)
}
render() {
return (
<ScrollView
style={styles.container}
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=> {this.scrollView.scrollToEnd({animated: true})}}
>
<KeyboardAvoidingView
behavior={Platform.OS == 'ios' ? "position" : null}
>
<View>
{this.renderMessages(this.state.messages)}
<View style={styles.textBox}>
<TextInput
style={styles.textInput}
placeholder='Reply...'
placeholderTextColor={'rgb(216,216,216)'}
returnKeyType='done'
autoCapitalize='none'
selectionColor='#3490dc'
multiline={true}
blurOnSubmit={true}
/>
</View>
</View>
</KeyboardAvoidingView>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
container: {
//flex: 1,
backgroundColor: 'rgb(0,0,0)'
},
textInput: {
color: 'rgb(255,255,255)',
fontSize: 18,
},
textBox: {
borderColor: '#242F39',
borderWidth: 2,
borderRadius: 2,
padding: 10,
paddingLeft: 16,
marginTop: 10,
backgroundColor: '#0A151F'
}
})
答案 0 :(得分:0)
尝试一下:
const screen = Dimensions.get('window');
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "height" : null}
keyboardVerticalOffset={Platform.OS === 'ios' ? screen.height * 0.25 : screen.height * 0.5}
style={{ flex: 1 }}
>
如果您在键盘动画方面遇到麻烦(我对此也有很多疑问)。您可以在此处将其删除,如下所示:
node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvodingView
这部分没有注释
if (duration && easing) {
LayoutAnimation.configureNext({
// We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m
duration: duration > 10 ? duration : 10,
update: {
duration: duration > 10 ? duration : 10,
type: LayoutAnimation.Types[easing] || 'keyboard',
},
});
}
答案 1 :(得分:0)
我最终将ScrollView放在KeyboardAvoidingView的内部,然后还使用填充而不是位置进行行为。然后,我还添加了键盘侦听器,以根据键盘的大小来修改视图下方的填充。
import React from 'react'
import { StyleSheet, View, Text, TextInput, ScrollView, KeyboardAvoidingView, Platform, NativeModules, Dimensions, SafeAreaView, Keyboard, Animated } from 'react-native'
import Message from './message'
const { StatusBarManager } = NativeModules
const screen = Dimensions.get('window')
export default class Messages extends React.Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: 'Messages',
headerStyle: {
backgroundColor: 'rgb(0,0,0)',
},
headerTitleStyle: {
fontSize: 20,
color: 'rgb(255,255,255)'
},
headerTintColor: 'rgb(0,122,255)',
})
state = {
messages: [],
keyboardPadding: new Animated.Value(0)
}
componentDidMount = () => {
Platform.OS == 'ios' ? StatusBarManager.getHeight((statusBarFrameData) => {
this.setState({statusBarHeight: statusBarFrameData.height})
}) : null
this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow)
this.keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide)
}
componentWillUnmount = () => {
this.keyboardWillShowListener.remove()
this.keyboardWillHideListener.remove()
}
keyboardWillShow = (e) => {
Animated.timing(this.state.keyboardPadding, { toValue: 1, duration: 0}).start()
}
keyboardWillHide = () => {
Animated.timing(this.state.keyboardPadding, { toValue: 0, duration: 0 }).start()
}
scrollStyles = (keyboardPadding) => {
return { paddingBottom: keyboardPadding }
}
renderMessages = (messages) => {
return messages.map((data, i) => <Message data={data} key={i}/>)
}
addMessage = (message) => {
let messageObj = {
message: message,
userId: 2,
userName: 'Sean'
}
this.setState({messages: [...this.state.messages, messageObj]})
}
render() {
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView
style={styles.keyboardContainer}
behavior={Platform.OS == 'ios' ? 'padding' : null}
keyboardVerticalOffset={this.state.statusBarHeight + 44}
>
<ScrollView
ref={ref => this.scrollView = ref}
onContentSizeChange={(contentWidth, contentHeight)=> {this.scrollView.scrollToEnd({animated: true})}}
>
<Animated.View style={this.scrollStyles(this.state.keyboardPadding)}>
{this.renderMessages(this.state.messages)}
</Animated.View>
</ScrollView>
<View style={styles.textBox}>
<TextInput
style={styles.textInput}
placeholder='Reply...'
placeholderTextColor={'rgb(216,216,216)'}
returnKeyType='done'
autoCapitalize='none'
selectionColor='#3490dc'
multiline={true}
blurOnSubmit={true}
onSubmitEditing={(e)=> this.addMessage(e.nativeEvent.text)}
/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgb(0,0,0)'
},
keyboardContainer: {
flex: 1,
backgroundColor: 'rgb(0,0,0)'
},
textInput: {
color: 'rgb(255,255,255)',
fontSize: 18,
},
textBox: {
borderColor: '#242F39',
borderWidth: 1,
borderRadius: 2,
padding: 10,
paddingLeft: 16,
backgroundColor: '#0A151F',
},
})