如何防止自动增长的文本输入容器在 react-native 中在键盘后面增长
How to prevent auto-grow text input container from growing behind keyboard in react-native
目标:创建一个文本输入字段,它会随着输入行的扩展而响应地扩展,直到某个点,就像大多数消息传递应用程序一样。
问题:随着输入扩展超过 3 或 4 行,而不是输入容器的顶部向上扩展,输入容器根据内容大小扩展,这是应该的,但容器被重新定位在 keyboard/keyboard 单词建议,重新定位左侧按钮(输入容器的一部分)以及 <TextInput>
本身。
下图显示了我希望填充物位于底部的方式。 "lower container" 包含按钮和输入字段。灰白色是键盘建议的顶部 (iOS)
下图显示了不良行为。你可以看到输入的底部边框,以及按钮开始消失在建议 box/keyboard 后面。如果输入不断扩大,底部边框和按钮将逐渐变得不那么明显。
这是整个屏幕组件:
render () {
return (
<KeyboardAvoidingView
style={{ flex: 1, backgroundColor: Colors.PRIMARY_OFF_WHITE,
}}
behavior={Platform.OS === 'ios' ? 'position' : null}
keyboardVerticalOffset={Platform.OS === 'ios' ?hp("11%") : 0}
>
/* Upper Container */
<View style={{ justifyContent: 'flex-start', height: height*0.8, paddingBottom: 10 }}>
<FlatList
data={this.props.messages}
ref={'list'}
onContentSizeChange={() => this.refs.list.scrollToEnd()}
keyExtractor={(item) => {
return (
item.toString() +
new Date().getTime().toString() +
Math.floor(Math.random() * Math.floor(new Date().getTime())).toString()
);
}}
renderItem={({ item, index }) => {
return (
<Components.ChatMessage
isSender={item.sender == this.props.uid ? true : false}
message={item.content.data}
read={item.read}
time={item.time}
onPress={() =>
this.props.readMsg(
{
id: this.props.uid,
role: this.props.role,
convoId: this.state.ownerConvoId
},
item.docId,
this.props.navigation.state.params.uid
)}
/>
);
}}
/>
</View>
/* Lower Container */
<View
style={{
height: this.state.height+20,
flexDirection: 'row',
alignItems: 'center',
justifyContent:"space-around",
paddingVertical: 10
}}
>
<Components.OptionFan
options={[
{
icon: require('../assets/img/white-voice.png'),
onPress: () => {
this.props.navigation.navigate('Schedule', {
receiver: this.conversants.receiver,
sender: this.conversants.sender,
type: 'Voice'
});
},
key: 1
},
{
icon: require('../assets/img/white-video.png'),
onPress: () => {
this.props.navigation.navigate('Schedule', {
receiver: this.conversants.receiver,
sender: this.conversants.sender,
type: 'Video'
});
},
key: 2
}
]}
/>
<TextInput
multiline={true}
textAlignVertical={'center'}
onChangeText={(text) => this.setState({ text })}
onFocus={() => this.refs.list.scrollToEnd()}
onContentSizeChange={(event) =>
this.setState({
height:
event.nativeEvent.contentSize.height <= 40
? 40
: event.nativeEvent.contentSize.height
})}
style={{
height: Math.max(40, this.state.height),
width: wp('80%'),
borderWidth: 1,
alignSelf: this.state.height > 40 ? "flex-end":null,
borderColor: Colors.PRIMARY_GREEN,
borderRadius: 18,
paddingLeft: 15,
paddingTop: 10,
paddingRight: 15
}}
ref={'input'}
blurOnSubmit={true}
returnKeyType={'send'}
placeholder={'Write a message...'}
onSubmitEditing={() => {
if (this.props.role == 'Influencer') {
this.send();
this.refs.input.clear();
} else {
this.setState({ visible: true });
}
}}
/>
</View>
</KeyboardAvoidingView>
);
}
我怎样才能实现一个在底部具有所需填充的视图中的生长?
编辑:明确地说,这个问题不是关于如何制作自动增长的输入字段。上面的代码已经完成了。它是关于自动增长输入字段所在的容器,以及父容器、输入字段和按钮如何增长 behind keyboard/keyboard 建议。 目标 是让文本输入始终 直接显示在键盘上方,input/button/container 的底部始终相同space在键盘之间,而高度只向上扩展。
此处发布的问题类似:In React Native, How to have multiple multiline textinputs that don't hide behind the keyboard in one scrollable form?
您可以将父容器设置为“100%”高度并调整上部内容的大小,以便输入容器始终向上增长。
一个简单的实现如下。 textInputHeight
取自状态,并在 TextInput
调整大小时设置。
return (
<KeyboardAvoidingView
style={{height: '100%'}}
behavior={Platform.OS === 'ios' ? 'position' : undefined}
keyboardVerticalOffset={100}>
<ScrollView
style={{
backgroundColor: '#777',
height: height - (80 + textInputHeight),
}}>
<View style={{height: 1000}} />
</ScrollView>
<TextInput
multiline={true}
onLayout={(event) => {
if (textInputHeight === 0) {
setTextInputHeight(event.nativeEvent.layout.height);
}
}}
onContentSizeChange={(event) => {
setTextInputHeight(event.nativeEvent.contentSize.height);
}}
/>
</KeyboardAvoidingView>
);
作为附加说明,在考虑屏幕部分的动态高度时,请始终记住要考虑状态栏(显然是 iOS 和 android)以及讨厌的软 Android 屏幕底部的导航栏,因为在为 'window' 使用维度 api 时未将其考虑在内。我忽略这一点的错误。
获取状态栏和导航栏:
import {NativeModules, Platform} from 'react-native';
const { StatusBarManager } = NativeModules; // Note: StatusBar API is not good used here because of platform inconsistencies.
// Note: 'window' does not contain Android/iOS status bar or Android soft Navigation Bar
const WINDOW_HEIGHT = Dimensions.get('window').height;
// 'screen' gets full hardware dimension
const DEVICE_HEIGHT = Dimensions.get('screen').height;
const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? 20 : StatusBarManager.HEIGHT;
const ANDROID_NAV_HEIGHT = Platform.OS === 'ios' ? 0 : DEVICE_HEIGHT - (WINDOW_HEIGHT + STATUSBAR_HEIGHT);
目标:创建一个文本输入字段,它会随着输入行的扩展而响应地扩展,直到某个点,就像大多数消息传递应用程序一样。
问题:随着输入扩展超过 3 或 4 行,而不是输入容器的顶部向上扩展,输入容器根据内容大小扩展,这是应该的,但容器被重新定位在 keyboard/keyboard 单词建议,重新定位左侧按钮(输入容器的一部分)以及 <TextInput>
本身。
下图显示了我希望填充物位于底部的方式。 "lower container" 包含按钮和输入字段。灰白色是键盘建议的顶部 (iOS)
下图显示了不良行为。你可以看到输入的底部边框,以及按钮开始消失在建议 box/keyboard 后面。如果输入不断扩大,底部边框和按钮将逐渐变得不那么明显。
这是整个屏幕组件:
render () {
return (
<KeyboardAvoidingView
style={{ flex: 1, backgroundColor: Colors.PRIMARY_OFF_WHITE,
}}
behavior={Platform.OS === 'ios' ? 'position' : null}
keyboardVerticalOffset={Platform.OS === 'ios' ?hp("11%") : 0}
>
/* Upper Container */
<View style={{ justifyContent: 'flex-start', height: height*0.8, paddingBottom: 10 }}>
<FlatList
data={this.props.messages}
ref={'list'}
onContentSizeChange={() => this.refs.list.scrollToEnd()}
keyExtractor={(item) => {
return (
item.toString() +
new Date().getTime().toString() +
Math.floor(Math.random() * Math.floor(new Date().getTime())).toString()
);
}}
renderItem={({ item, index }) => {
return (
<Components.ChatMessage
isSender={item.sender == this.props.uid ? true : false}
message={item.content.data}
read={item.read}
time={item.time}
onPress={() =>
this.props.readMsg(
{
id: this.props.uid,
role: this.props.role,
convoId: this.state.ownerConvoId
},
item.docId,
this.props.navigation.state.params.uid
)}
/>
);
}}
/>
</View>
/* Lower Container */
<View
style={{
height: this.state.height+20,
flexDirection: 'row',
alignItems: 'center',
justifyContent:"space-around",
paddingVertical: 10
}}
>
<Components.OptionFan
options={[
{
icon: require('../assets/img/white-voice.png'),
onPress: () => {
this.props.navigation.navigate('Schedule', {
receiver: this.conversants.receiver,
sender: this.conversants.sender,
type: 'Voice'
});
},
key: 1
},
{
icon: require('../assets/img/white-video.png'),
onPress: () => {
this.props.navigation.navigate('Schedule', {
receiver: this.conversants.receiver,
sender: this.conversants.sender,
type: 'Video'
});
},
key: 2
}
]}
/>
<TextInput
multiline={true}
textAlignVertical={'center'}
onChangeText={(text) => this.setState({ text })}
onFocus={() => this.refs.list.scrollToEnd()}
onContentSizeChange={(event) =>
this.setState({
height:
event.nativeEvent.contentSize.height <= 40
? 40
: event.nativeEvent.contentSize.height
})}
style={{
height: Math.max(40, this.state.height),
width: wp('80%'),
borderWidth: 1,
alignSelf: this.state.height > 40 ? "flex-end":null,
borderColor: Colors.PRIMARY_GREEN,
borderRadius: 18,
paddingLeft: 15,
paddingTop: 10,
paddingRight: 15
}}
ref={'input'}
blurOnSubmit={true}
returnKeyType={'send'}
placeholder={'Write a message...'}
onSubmitEditing={() => {
if (this.props.role == 'Influencer') {
this.send();
this.refs.input.clear();
} else {
this.setState({ visible: true });
}
}}
/>
</View>
</KeyboardAvoidingView>
);
}
我怎样才能实现一个在底部具有所需填充的视图中的生长?
编辑:明确地说,这个问题不是关于如何制作自动增长的输入字段。上面的代码已经完成了。它是关于自动增长输入字段所在的容器,以及父容器、输入字段和按钮如何增长 behind keyboard/keyboard 建议。 目标 是让文本输入始终 直接显示在键盘上方,input/button/container 的底部始终相同space在键盘之间,而高度只向上扩展。
此处发布的问题类似:In React Native, How to have multiple multiline textinputs that don't hide behind the keyboard in one scrollable form?
您可以将父容器设置为“100%”高度并调整上部内容的大小,以便输入容器始终向上增长。
一个简单的实现如下。 textInputHeight
取自状态,并在 TextInput
调整大小时设置。
return (
<KeyboardAvoidingView
style={{height: '100%'}}
behavior={Platform.OS === 'ios' ? 'position' : undefined}
keyboardVerticalOffset={100}>
<ScrollView
style={{
backgroundColor: '#777',
height: height - (80 + textInputHeight),
}}>
<View style={{height: 1000}} />
</ScrollView>
<TextInput
multiline={true}
onLayout={(event) => {
if (textInputHeight === 0) {
setTextInputHeight(event.nativeEvent.layout.height);
}
}}
onContentSizeChange={(event) => {
setTextInputHeight(event.nativeEvent.contentSize.height);
}}
/>
</KeyboardAvoidingView>
);
作为附加说明,在考虑屏幕部分的动态高度时,请始终记住要考虑状态栏(显然是 iOS 和 android)以及讨厌的软 Android 屏幕底部的导航栏,因为在为 'window' 使用维度 api 时未将其考虑在内。我忽略这一点的错误。
获取状态栏和导航栏:
import {NativeModules, Platform} from 'react-native';
const { StatusBarManager } = NativeModules; // Note: StatusBar API is not good used here because of platform inconsistencies.
// Note: 'window' does not contain Android/iOS status bar or Android soft Navigation Bar
const WINDOW_HEIGHT = Dimensions.get('window').height;
// 'screen' gets full hardware dimension
const DEVICE_HEIGHT = Dimensions.get('screen').height;
const STATUS_BAR_HEIGHT = Platform.OS === 'ios' ? 20 : StatusBarManager.HEIGHT;
const ANDROID_NAV_HEIGHT = Platform.OS === 'ios' ? 0 : DEVICE_HEIGHT - (WINDOW_HEIGHT + STATUSBAR_HEIGHT);