如何在React Native中输入字段时将文本输入框设置在键盘上方

34

我正在使用React Native的TextInput组件。在此,如果用户单击textInput字段,则需要显示InputBox在键盘上方。

我尝试过以下方法,但我遇到了问题

1. 键盘避免视图(Keyboard avoiding view)

 a. Here it shows some empty space below the input box 
 b. Manually I need to scroll up the screen to see the input field which I was given in the text field
 c. Input box section is hiding while placing the mouse inside the input box 

2. react-native-Keyboard-aware-scroll-view

a.It shows some empty space below the input box
b.ScrollView is reset to the top of the page after I moving to the next input box

我在ScrollView组件中设置了Keyboard-aware-scroll-view。

请说明一下。

我的示例代码如下:

<SafeAreaView>
<KeyboardAvoidingView>
<ScrollView>        
        <Text>Name</Text>
            <AutoTags
            //required
             suggestions={this.state.suggestedName}
             handleAddition={this.handleAddition}
             handleDelete={this.handleDelete}
             multiline={true}
             placeholder="TYPE IN"
             blurOnSubmit={true}
             style= {styles.style}
             />
</ScrollView>   
</KeyboardAvoidingView>
</SafeAreaView>

[https://github.com/APSL/react-native-keyboard-aware-scroll-view]


尝试为KeyboardAvoidingView设置行为,并确保您的容器视图样式是flex。 - Omar Samman
我已经为KeyboardAvoidingView设置了behavior='padding'和style={{flex:1}}。 <KeyboardAvoidingView style={{flex:1}} behavior='padding'> <View> <Text>名称</Text> <View> <TextInput placeholder="输入内容"/> </View> </View> </KeyboardAvoidingView> - sejn
我需要在React Native中实现这种行为。当移动到文本输入框时,键盘会自动打开并在按下返回键后关闭。https://github.com/Just-/UIViewController-KeyboardAnimation - sejn
你可以尝试将<View>标签移除,只在<KeyboardAvoidingView>外面放置一个标签吗? - kenmistry
不确定为什么您撤销了我的编辑。如果您能在问题描述中放置代码,那肯定会有所帮助。 - kenmistry
@kenmistry 我已经添加了我的示例代码。它将不会显示在键盘上方的inputText框。我想要滚动以查看我正在文本框中输入哪个输入。Autotags具有和TextInput框相同的属性。 - sejn
17个回答

23

您可以使用scrollview并将所有组件放在其中,并向scrollview添加automaticallyAdjustKeyboardInsets属性,它将解决您的问题。

automaticallyAdjustKeyboardInsets控制ScrollView是否应自动调整其contentInset和scrollViewInsets,当键盘更改其大小时。默认值为false。

<ScrollView automaticallyAdjustKeyboardInsets={true}>

          {allChildComponentsHere}
         <View style={{ height: 30 }} />//added some extra space to last element
</ScrollView>

希望这有所帮助。


15

给你的TextInput添加position: absolute样式,并使用keyboardDidShow和keyboardDidHide事件返回的高度来改变它的位置。

以下是React Native 文档中键盘示例的修改版本,仅供演示:

import React, { Component } from 'react';
import { Keyboard, TextInput } from 'react-native';

class Example extends Component {
    state = {
        keyboardOffset: 0,
    };

    componentDidMount() {
        this.keyboardDidShowListener = Keyboard.addListener(
            'keyboardDidShow',
            this._keyboardDidShow,
        );
        this.keyboardDidHideListener = Keyboard.addListener(
            'keyboardDidHide',
            this._keyboardDidHide,
        );
    }

    componentWillUnmount() {
        this.keyboardDidShowListener.remove();
        this.keyboardDidHideListener.remove();
    }

    _keyboardDidShow(event) {
        this.setState({
            keyboardOffset: event.endCoordinates.height,
        })
    }

    _keyboardDidHide() {
        this.setState({
            keyboardOffset: 0,
        })
    }

    render() {
        return <View style={{flex: 1}}>
            <TextInput
                style={{
                    position: 'absolute',
                    width:    '100%',
                    bottom:   this.state.keyboardOffset,
                }}
                onSubmitEditing={Keyboard.dismiss}
            />
        </View>;
    }
}

1
我已经尝试过这个。但在AutoTags中它并没有像我预期的那样工作。 - sejn
嗨,我正在尝试上面的代码,但我注意到页面内容(在我的情况下是FlatList)因为bottom: this.state.keyboardOffset而跳动。此外,似乎event.endCoordinates.height返回的值比键盘高,因为TextInputKeyboard之间有一个间隙。 - Yasir
@Yasir "absolute"定位的元素是相对于其包含视图定位的,而这个视图的大小可能与设备不同。如果您的TextInput位于一个比设备高度小的容器内,您需要考虑容器和设备之间高度差异。这是一个适用于我将“Text”视图直接定位在键盘上方的公式:bottom: keyboardHeight - ((deviceHeight - containerHeight) / 2)。我有一个顶部和底部的栏,我的Text视图在两者之间的一个容器中,所以我考虑了设备高度和我的容器之间的差异。 - StoriKnow
1
不要这样做,这会导致布局卡顿。 - famfamfam

14

首先,您不需要为Android平台编写任何额外的代码。只需将输入保留在 ScrollView 内即可。对于iOS平台,只需使用 KeyboardAvoidingView 封装 ScrollView

创建以下函数以保存所有输入:

renderInputs = () => {
    return (<ScrollView
        showsVerticalScrollIndicator={false}
        style={{
            flex: 1,
        }}
        contentContainerStyle={{
            flexGrow: 1,
        }}>
        <Text>Enter Email</Text>
        <TextInput
            style={styles.text}
            underlineColorAndroid="transparent"
        />
    </ScrollView>)
}

然后按照以下方式在主视图中呈现它们

{Platform.OS === 'android' ? (
    this.renderInputs()
) : (
    <KeyboardAvoidingView behavior="padding">
        {this.renderInputs()}
    </KeyboardAvoidingView>
)}

我曾使用过这种方法,可以保证它有效。如果不起作用,那么你可能漏掉了某些东西。


2
你也可以在Android上使用KeyboardAvoidingView。只需设置behavior="height"即可,无需渲染函数。 - Pawel

11

Hooks版本:

const [keyboardOffset, setKeyboardOffset] = useState(0);
const onKeyboardShow = event => setKeyboardOffset(event.endCoordinates.height);
const onKeyboardHide = () => setKeyboardOffset(0);
const keyboardDidShowListener = useRef();
const keyboardDidHideListener = useRef();

useEffect(() => {
  keyboardDidShowListener.current = Keyboard.addListener('keyboardWillShow', onKeyboardShow);
  keyboardDidHideListener.current = Keyboard.addListener('keyboardWillHide', onKeyboardHide);

  return () => {
    keyboardDidShowListener.current.remove();
    keyboardDidHideListener.current.remove();
  };
}, []);

1
<TextInput style={{marginBottom:keyboardOffset}}/> - Gurjinder Singh
1
在我的情况下,keyboardDidShowkeyboardDidHide事件起作用了。 - Muhammad Adeel Shoukat
对于TypeScript,您需要像这样为事件和ref添加类型:const onKeyboardShow = (event: { endCoordinates: { height: React.SetStateAction<number> } }) => setKeyboardOffset(event.endCoordinates.height); const onKeyboardHide = () => setKeyboardOffset(0); const keyboardDidShowListener = useRef<EmitterSubscription>(); const keyboardDidHideListener = useRef<EmitterSubscription>(); - airowe

6

您可以按以下方式使用KeyboardAvoidingView

if (Platform.OS === 'ios') {
        return <KeyboardAvoidingView behavior="padding">
            {this.renderChatInputSection()}
        </KeyboardAvoidingView>
    } else {
        return this.renderChatInputSection()
    }

this.renderChatInputSection() 将返回类似于文本输入框的视图,用于输入消息。希望这能帮到你。


我会尝试这个并让您知道。 - sejn
尝试使用react-native-keyboard-aware-scroll-view替换ScrollView。 - Maneesh
输入完毕后,输入框下方将显示一个空格。 - sejn
@seijn 给它一个样式 {flexGrow: 1} - Fotios Tsakiris

2
请将以下两行代码添加到您的Android应用程序中的 AndroidManifest.xml 文件内 activity 标签中: android:launchMode="singleTask" android:windowSoftInputMode="stateAlwaysHidden|adjustPan"

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

2
对于安卓系统,您可以在AndroidManifest文件中为Activity设置android:windowSoftInputMode="adjustResize",这样当键盘显示时,屏幕将会调整大小,如果您将TextInput放置在屏幕底部,它将保持在键盘之上。

1
那iOS呢? - C-lio Garcia

0

flexGrow: 1 是关键。

用法如下:

<ScrollView contentContainerStyle={styles.container}>
  <TextInput
    label="Note"
    value={currentContact.note}
    onChangeText={(text) => setAttribute("note", text)}
  />
</ScrollView>

const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
  },
});

0

react-native-keyboard-aware-scroll-view在iOS上引发了类似的问题。那时我遇到了react-native-keyboard-aware-view。代码片段几乎相同。

    <KeyboardAwareView animated={true}>
        <View style={{flex: 1}}>
          <ScrollView style={{flex: 1}}>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>A</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>B</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>C</Text>
              <Text style={{fontSize: 20, color: '#FFFFFF'}}>D</Text>
          </ScrollView>
        </View>
        <TouchableOpacity style={{height: 50, backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center', alignSelf: 'stretch'}}>
          <Text style={{fontSize: 20, color: '#FFFFFF'}}>Submit</Text>
        </TouchableOpacity>
      </KeyboardAwareView>

希望它有所帮助


这里不是文本,而是从React Native自动标记渲染的TextInput框。 - sejn

0

你一定会从这里找到有用的内容

键盘感知滚动视图Android问题

我真的不知道为什么你要添加

"androidStatusBar": { "backgroundColor": "#000000" }

才能让KeyboardawareScrollview正常工作

注意:别忘了重新启动项目,否则可能无法生效。 祝使用愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接