React Native:如何在按下“下一个”键盘button后select下一个TextInput?
我定义了两个TextInput字段,如下所示:
<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" /> <TextInput style = {styles.descriptionInput} multiline = {true} maxLength = {200} placeholder = "Description" />
但是按下键盘上的“下一步”button后,我的反应本机应用程序不会跳转到第二个TextInput字段。 我怎样才能做到这一点?
谢谢!
将焦点设置在最后一个onSubmitEditing上的下一个文本input上。 试试..
<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" onSubmitEditing={(event) => { this.refs.SecondInput.focus(); }} /> <TextInput ref='SecondInput' style = {styles.descriptionInput} multiline = {true} maxLength = {200} placeholder = "Description" />
你可以做到这一点, 而不使用裁判 。 这种方法是首选,因为参考可能会导致脆弱的代码 。 React文档build议尽可能find其他解决scheme:
如果您还没有使用React编写多个应用程序,您的第一个倾向通常是尝试在应用程序中使用参考“让事情发生”。 如果是这样的话,花一点时间,仔细想一想组件层次结构中应该拥有哪个状态。 通常情况下,很显然,“拥有”这个国家的适当位置在层级中处于更高的层次。 将状态放在那里通常会消除使用引用来“使事情发生”的愿望 – 相反,数据stream通常会实现您的目标。
相反,我们将使用状态variables来聚焦第二个input字段。
-
添加一个状态variables,我们将作为一个道具传递给
DescriptionInput
:initialState() { return { focusDescriptionInput: false, }; }
-
定义一个将此状态variables设置为true的处理程序方法:
handleTitleInputSubmit() { this.setState(focusDescriptionInput: true); }
-
在提交/击中
TitleInput
上的enter / nextTitleInput
,我们将调用handleTitleInputSubmit
。 这将设置focusDescriptionInput
为true。<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" onSubmitEditing={this.handleTitleInputSubmit} />
-
DescriptionInput
的focus
道具被设置为我们的focusDescriptionInput
状态variables。 因此,当focusDescriptionInput
发生变化时(在步骤3中),将使用focus={true}
重新呈现DescriptionInput
。<TextInput style = {styles.descriptionInput} multiline = {true} maxLength = {200} placeholder = "Description" focus={this.state.focusDescriptionInput} />
这是避免使用refs的好方法,因为refs会导致更脆弱的代码:)
编辑:h / t to @LaneRettig指出你需要用一些附加的道具和方法来包装React Native TextInput来让它响应focus
:
// Props: static propTypes = { focus: PropTypes.bool, } static defaultProps = { focus: false, } // Methods: focus() { this._component.focus(); } componentWillReceiveProps(nextProps) { const {focus} = nextProps; focus && this.focus(); }
从React Native 0.36开始,不再支持在文本input节点上调用focus()
(正如其他几个答案中所build议的那样)。 相反,您可以使用React Native中的TextInputState
模块。 我创build了以下帮助程序模块以使其更容易:
// TextInputManager // // Provides helper functions for managing the focus state of text // inputs. This is a hack! You are supposed to be able to call // "focus()" directly on TextInput nodes, but that doesn't seem // to be working as of ReactNative 0.36 // import { findNodeHandle } from 'react-native' import TextInputState from 'react-native/lib/TextInputState' export function focusTextInput(node) { try { TextInputState.focusTextInput(findNodeHandle(node)) } catch(e) { console.log("Couldn't focus text input: ", e.message) } }
然后,可以在TextInput
任何“ref”上调用focusTextInput
函数。 例如:
... <TextInput onSubmit={() => focusTextInput(this.refs.inputB)} /> <TextInput ref="inputB" /> ...
我创build了一个这样的小型库,除了replace包装视图和导入TextInput之外,不需要更改代码:
import { Form, TextInput } from 'react-native-autofocus' export default () => ( <Form> <TextInput placeholder="test" /> <TextInput placeholder="test 2" /> </Form> )
https://github.com/zackify/react-native-autofocus
在这里详细解释: https : //zach.codes/autofocus-inputs-in-react-native/
如果你碰巧正在使用tcomb-form-native
,你也可以这样做。 这里有个技巧:不是直接设置TextInput
的道具,而是通过options
。 您可以参考表单的字段:
this.refs.form.getComponent('password').refs.input.focus()
所以最终的产品看起来像这样:
var t = require('tcomb-form-native'); var Form = t.form.Form; var MyForm = t.struct({ field1: t.String, field2: t.String, }); var MyComponent = React.createClass({ _getFormOptions () { return { fields: { field1: { returnKeyType: 'next', onSubmitEditing: () => {this.refs.form.getComponent('field2').refs.input.focus()}, }, }, }; }, render () { var formOptions = this._getFormOptions(); return ( <View style={styles.container}> <Form ref="form" type={MyForm} options={formOptions}/> </View> ); }, });
(感谢remcoanker发布这个想法: https : //github.com/gcanti/tcomb-form-native/issues/96 )
使用react-native 0.45.1我也遇到了一些问题,试图在按下用户名TextInput上的返回键之后将焦点设置为密码TextInput。
在尝试了大部分顶级解决scheme之后,我在github上find了满足我需求的解决scheme: https : //github.com/shoutem/ui/issues/44#issuecomment-290724642
把它们加起来:
import React, { Component } from 'react'; import { TextInput as RNTextInput } from 'react-native'; export default class TextInput extends Component { render() { const { props } = this; return ( <RNTextInput {...props} ref={(input) => props.inputRef && props.inputRef(input)} /> ); } }
然后我使用它:
import React, {Component} from 'react'; import { View, } from 'react-native'; import TextInput from "../../components/TextInput"; class Login extends Component { constructor(props) { super(props); this.passTextInput = null } render() { return ( <View style={{flex:1}}> <TextInput style={{flex:1}} placeholder="Username" onSubmitEditing={(event) => { this.passTextInput.focus() }} /> <TextInput style={{flex:1}} placeholder="Password" inputRef={(input) => { this.passTextInput = input }} /> </View> ) } }
在React Native的GitHub问题上试试这个解决scheme。
https://github.com/facebook/react-native/pull/2149#issuecomment-129262565
您需要为TextInput组件使用ref prop。
然后你需要创build一个函数,在onSubmitEditing道具上调用,将焦点移到第二个TextInput参考。
var InputScreen = React.createClass({ _focusNextField(nextField) { this.refs[nextField].focus() }, render: function() { return ( <View style={styles.container}> <TextInput ref='1' style={styles.input} placeholder='Normal' returnKeyType='next' blurOnSubmit={false} onSubmitEditing={() => this._focusNextField('2')} /> <TextInput ref='2' style={styles.input} keyboardType='email-address' placeholder='Email Address' returnKeyType='next' blurOnSubmit={false} onSubmitEditing={() => this._focusNextField('3')} /> <TextInput ref='3' style={styles.input} keyboardType='url' placeholder='URL' returnKeyType='next' blurOnSubmit={false} onSubmitEditing={() => this._focusNextField('4')} /> <TextInput ref='4' style={styles.input} keyboardType='numeric' placeholder='Numeric' blurOnSubmit={false} onSubmitEditing={() => this._focusNextField('5')} /> <TextInput ref='5' style={styles.input} keyboardType='numbers-and-punctuation' placeholder='Numbers & Punctuation' returnKeyType='done' /> </View> ); } });
使用callback引用而不是传统的string引用:
<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" onSubmitEditing={() => {this.nextInput.focus()}} /> <TextInput style = {styles.descriptionInput} multiline = {true} maxLength = {200} placeholder = "Description" ref={nextInput => this.nextInput = nextInput} />
有一种方法可以捕获TextInput
选项卡 。 这是hacky,但总比没有好 。
定义一个onChangeText
处理程序,将新的input值与旧的进行比较,检查\t
。 如果find一个,按照@boredgames所示前进该字段
假设variablesusername
包含username
的值, setUsername
调度一个动作来改变它在商店(组件状态,REDEX存储等),做这样的事情:
function tabGuard (newValue, oldValue, callback, nextCallback) { if (newValue.indexOf('\t') >= 0 && oldValue.indexOf('\t') === -1) { callback(oldValue) nextCallback() } else { callback(newValue) } } class LoginScene { focusNextField = (nextField) => { this.refs[nextField].focus() } focusOnPassword = () => { this.focusNextField('password') } handleUsernameChange = (newValue) => { const { username } = this.props // or from wherever const { setUsername } = this.props.actions // or from wherever tabGuard(newValue, username, setUsername, this.focusOnPassword) } render () { const { username } = this.props return ( <TextInput ref='username' placeholder='Username' autoCapitalize='none' autoCorrect={false} autoFocus keyboardType='email-address' onChangeText={handleUsernameChange} blurOnSubmit={false} onSubmitEditing={focusOnPassword} value={username} /> ) } }
对于可接受的解决scheme,如果你的TextInput
在另一个组件内,你需要从ref
“popup”引用到父容器。
// MyComponent render() { <View> <TextInput ref={(r) => this.props.onRef(r)} { ...this.props }/> </View> } // MyView render() { <MyComponent onSubmitEditing={(evt) => this.myField2.focus()}/> <MyComponent onRef={(r) => this.myField2 = r}/> }
在你的组件中:
constructor(props) { super(props); this.focusNextField = this .focusNextField .bind(this); // to store our input refs this.inputs = {}; } focusNextField(id) { console.log("focus next input: " + id); this .inputs[id] ._root .focus(); }
注意:我使用._root
因为它是NativeBase'Library'Input中 TextInput的引用
并在你的文字input这样
<TextInput onSubmitEditing={() => { this.focusNextField('two'); }} returnKeyType="next" blurOnSubmit={false}/> <TextInput ref={input => { this.inputs['two'] = input; }}/>
这里是用于具有聚焦属性的input组件的试剂溶液。
只要这个道具被设置为真,只要这个道理是错误的,这个领域就会被聚焦。
不幸的是,这个组件需要有一个:ref定义,我找不到其他的方式来调用.focus()。 我对build议感到高兴。
(defn focusable-input [init-attrs] (r/create-class {:display-name "focusable-input" :component-will-receive-props (fn [this new-argv] (let [ref-c (aget this "refs" (:ref init-attrs)) focus (:focus (ru/extract-props new-argv)) is-focused (.isFocused ref-c)] (if focus (when-not is-focused (.focus ref-c)) (when is-focused (.blur ref-c))))) :reagent-render (fn [attrs] (let [init-focus (:focus init-attrs) auto-focus (or (:auto-focus attrs) init-focus) attrs (assoc attrs :auto-focus auto-focus)] [input attrs]))}))
https://gist.github.com/Knotschi/6f97efe89681ac149113ddec4c396cc5