Ios React Native(反应本机):如何在按下";后选择下一个文本输入;“下一步”;键盘按钮?

Ios React Native(反应本机):如何在按下";后选择下一个文本输入;“下一步”;键盘按钮?,ios,react-native,Ios,React Native,我定义了两个TextInput字段,如下所示: <TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" /> <TextInput style = {styles.descriptionInput} multiline = {true} maxLength = {

我定义了两个TextInput字段,如下所示:

<TextInput 
   style = {styles.titleInput}
   returnKeyType = {"next"}
   autoFocus = {true}
   placeholder = "Title" />
<TextInput
   style = {styles.descriptionInput}          
   multiline = {true}
   maxLength = {200}
   placeholder = "Description" />

但按下键盘上的“下一步”按钮后,我的react原生应用程序不会跳转到第二个文本输入字段。我怎样才能做到这一点


谢谢

针对React Native的GitHub问题尝试此解决方案

您需要为TextInput组件使用ref prop。
然后需要创建一个函数,该函数在Submitediting prop上被调用,该prop将焦点移动到第二个TextInput ref上

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>
        );
    }
});
var InputScreen=React.createClass({
_focusNextField(下一个字段){
this.refs[nextField].focus()
},
render:function(){
返回(
此._focusNextField('2')}
/>
此._focusNextField('3')}
/>
此._focusNextField('4')}
/>
此._focusNextField('5')}
/>
);
}
});

当上一个
TextInput
onSubmitEditing
被触发时,设置第二个
TextInput
焦点

试试这个

  • 向第二个文本输入添加引用
    ref={(输入)=>{this.secondTextInput=input;}}}

  • 将焦点函数绑定到第一个文本输入的Submitediting事件。
    onSubmitEditing={()=>{this.secondTextInput.focus();}}

  • 记住将blurOnSubmit设置为false,以防止键盘闪烁。
    blurOnSubmit={false}

  • 全部完成后,应该是这样的

    {this.secondTextInput.focus();}
    blurOnSubmit={false}
    />
    {this.secondTextInput=input;}}
    占位符=“secondTextInput”
    />
    
    您可以在不使用REF的情况下执行此操作。这种方法是首选的,因为REF会导致脆弱代码。顾问建议在可能的情况下找到其他解决方案:

    如果您尚未使用React编程多个应用程序,请首先 通常倾向于尝试使用ref来“制造事物” 在你的应用程序中“发生”。如果是这样的话,花点时间多想想 批判性地讨论在组件中应该在何处拥有状态 等级制度通常情况下,很明显,正确的“拥有”位置 状态在层次结构中处于较高级别。把国家放在那里 通常消除了使用REF“使事情发生”的欲望- 相反,数据流通常会实现您的目标

    相反,我们将使用状态变量来聚焦第二个输入字段

  • 添加一个状态变量,我们将其作为道具传递到
    说明输入中

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  • 定义将此状态变量设置为true的处理程序方法:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  • 标题输入
    上提交/点击回车/下一步后,我们将调用
    HandletInputSubmit
    。这将把
    focusDescriptionInput
    设置为true

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  • 这是避免使用refs的好方法,因为refs会导致更脆弱的代码:)

    编辑:h/t至@LaneRettig,指出您需要使用一些附加的道具和方法包装React Native TextInput,以使其响应
    焦点

        // Props:
        static propTypes = { 
            focus: PropTypes.bool,
        } 
    
        static defaultProps = { 
            focus: false,
        } 
    
        // Methods:
        focus() {
            this._component.focus(); 
        } 
    
        componentWillReceiveProps(nextProps) {
            const {focus} = nextProps; 
    
            focus && this.focus(); 
        }
    
    如果你碰巧像我一样使用,你也可以这样做。诀窍在于:不要直接设置
    文本输入的道具,而是通过
    选项设置。您可以将表单的字段引用为:

    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>
        );
      },
    });
    
    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} />
        )
      }
    }
    
    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>
            )
        }
    }
    
       export default class CustomBoladonesTextInput extends React.Component {
          render() {        
             return (< TextInput ref={this.props.refInner} ... />);     
          } 
       }
    
    var t=require('tcomb-form-native');
    var Form=t.Form.Form;
    var MyForm=t.struct({
    字段1:t.字符串,
    字段2:t.字符串,
    });
    var MyComponent=React.createClass({
    _getFormOptions(){
    返回{
    字段:{
    字段1:{
    returnKeyType:“下一个”,
    onSubmitEditing:()=>{this.refs.form.getComponent('field2').refs.input.focus()},
    },
    },
    };
    },
    渲染(){
    var formOptions=this._getFormOptions();
    返回(
    );
    },
    });
    

    (这要归功于Remcanker在这里发布的想法:)

    这里是一种输入成分的试剂溶液,具有:焦点属性

    只要该道具设置为true,该场就会聚焦,只要该道具设置为false,该场就不会聚焦

    不幸的是,这个组件需要定义一个:ref,我找不到其他方法来调用它的.focus()。我对这些建议感到高兴

    (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]))}))
    

    有一种方法可以在
    文本输入中捕获选项卡。这很粗糙,但比我好

    定义一个比较新输入值和旧输入值的
    onChangeText
    处理程序,检查
    \t
    。如果找到一个,则按@boredgames所示推进字段

    假设变量
    username
    包含用户名的值,并且
    setUsername
    在存储区(组件状态、redux存储区等)中发送一个操作来更改该值,请执行以下操作:

    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>
        );
      },
    });
    
    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} />
        )
      }
    }
    
    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>
            )
        }
    }
    
       export default class CustomBoladonesTextInput extends React.Component {
          render() {        
             return (< TextInput ref={this.props.refInner} ... />);     
          } 
       }
    
    函数tabGuard(newValue、oldValue、回调、nextCallback){
    if(newValue.indexOf('\t')>=0&&oldValue.indexOf('\t')=-1){
    回调(旧值)
    nextCallback()
    }否则{
    回调(newValue)
    }
    }
    类LoginScene{
    focusNextField=(nextField)=>{
    this.refs[nextField].focus()
    }
    焦点密码=()=>{
    此.focusNextField('密码')
    }
    handleUsernameChange=(newValue)=>{
    const{username}=this.props//或来自任何地方
    const{setUsername}=this.props.actions//或来自任何地方
    tabGuard(newValue、用户名、setUsername、this.focusOnPassword)
    }
    渲染(){
    const{username}=this.props
    返回(
    )
    }
    }
    
    使用回调引用而不是字符串引用:

    <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}
    />
    
    {this.nextInput.focus()}
    />
    this.nextInput=nextInput}
    />
    
    从React Native 0.36开始,调用
    focus()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>
            )
        }
    }
    
    import { Form, TextInput } from 'react-native-autofocus'
    
    export default () => (
      <Form>
        <TextInput placeholder="test" />
        <TextInput placeholder="test 2" />
      </Form>
    )
    
    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();
        }
    
    <TextInput
             onSubmitEditing={() => {
                              this.focusNextField('two');
                              }}
             returnKeyType="next"
             blurOnSubmit={false}/>
    
    
    <TextInput      
             ref={input => {
                  this.inputs['two'] = input;
                            }}/>
    
      <CustomBoladonesTextInput 
          onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
          returnKeyType="next"
          ... />
    
      <CustomBoladonesTextInput 
           ref={ref => this.customInput2 = ref}
           refInner="innerTextInput2"
           ... />
    
       export default class CustomBoladonesTextInput extends React.Component {
          render() {        
             return (< TextInput ref={this.props.refInner} ... />);     
          } 
       }
    
    <TextInput 
      autoFocus={true} 
      onSubmitEditing={() => {this.PasswordInputRef._root.focus()}} 
    />
    
    <TextInput ref={input => {this.PasswordInputRef = input}} />
    
    class Test extends React.Component {
      constructor(props) {
        super(props);
        this.secondTextInputRef = React.createRef();
      }
    
      render() {
        return(
            <View>
                <TextInput
                    placeholder = "FirstTextInput"
                    returnKeyType="next"
                    onSubmitEditing={() => { this.secondTextInputRef.current.focus(); }}
                />
                <TextInput
                    ref={this.secondTextInputRef}
                    placeholder = "secondTextInput"
                />
            </View>
        );
      }
    }
    
    <Item floatingLabel>
        <Label>Title</Label>
        <Input
            returnKeyType = {"next"}
            autoFocus = {true}
            onSubmitEditing={(event) => {
                this._inputDesc._root.focus(); 
            }} />
    </Item>
    <Item floatingLabel>
        <Label>Description</Label>
        <Input
            getRef={(c) => this._inputDesc = c}
            multiline={true} style={{height: 100}} />
            onSubmitEditing={(event) => { this._inputLink._root.focus(); }} />
    </Item>
    
    <TextInput placeholder="Nombre"
        ref="1"
        editable={true}
        returnKeyType="next"
        underlineColorAndroid={'#4DB6AC'}
        blurOnSubmit={false}
        value={this.state.First_Name}
        onChangeText={First_Name => this.setState({ First_Name })}
        onSubmitEditing={() => this.focusNextField('2')}
        placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />
    
    <TextInput placeholder="Apellido"
        ref="2"
        editable={true}
        returnKeyType="next"
        underlineColorAndroid={'#4DB6AC'}
        blurOnSubmit={false}
        value={this.state.Last_Name}
        onChangeText={Last_Name => this.setState({ Last_Name })}
        onSubmitEditing={() => this.focusNextField('3')}
        placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />
    
    focusNextField(nextField) {
        this.refs[nextField].focus();
    }
    
    <TextInput 
        keyboardType="email-address"
        placeholder="Email"
        returnKeyType="next"
        ref="email"
        onSubmitEditing={() => this.focusTextInput(this.refs.password)}
        blurOnSubmit={false}
     />
    <TextInput
        ref="password"
        placeholder="Password" 
        secureTextEntry={true} />
    
    private focusTextInput(node: any) {
        node.focus();
    }
    
    import React, { useRef } from 'react'
    ...
    
    
    const MyFormComponent = () => {
    
      const ref_input2 = useRef();
      const ref_input3 = useRef();
    
      return (
        <>
          <TextInput
            placeholder="Input1"
            autoFocus={true}
            returnKeyType="next"
            onSubmitEditing={() => ref_input2.current.focus()}
          />
          <TextInput
            placeholder="Input2"
            returnKeyType="next"
            onSubmitEditing={() => ref_input3.current.focus()}
            ref={ref_input2}
          />
          <TextInput
            placeholder="Input3"
            ref={ref_input3}
          />
        </>
      )
    }
    
    import React, { useState, useEffect, useRef, } from 'react';
    
    const OTP = (props) => {
    
    
    
        const OTP = [];
        const ref_input = [];
        ref_input[0] = useRef();
        ref_input[1] = useRef();
        ref_input[2] = useRef();
        ref_input[3] = useRef();
    
        const focusNext = (text, index) => {
            if (index < ref_input.length - 1 && text) {
                ref_input[index + 1].current.focus();
            }
            if (index == ref_input.length - 1) {
                ref_input[index].current.blur();
            }
            OTP[index] = text;
        }
        const focusPrev = (key, index) => {
            if (key === "Backspace" && index !== 0) {
                ref_input[index - 1].current.focus();
            }
        }
    
        return (
            <SafeAreaView>
                <View>
                    
                        <ScrollView contentInsetAdjustmentBehavior="automatic" showsVerticalScrollIndicator={false}>
                            <View style={loginScreenStyle.titleWrap}>
                                <Title style={loginScreenStyle.titleHeading}>Verify OTP</Title>
                                <Subheading style={loginScreenStyle.subTitle}>Enter the 4 digit code sent to your mobile number</Subheading>
                            </View>
                            <View style={loginScreenStyle.inputContainer}>
                                <TextInput
                                    mode="flat"
                                    selectionColor={Colors.primaryColor}
                                    underlineColorAndroid="transparent"
                                    textAlign='center'
                                    maxLength={1}
                                    keyboardType='numeric'
                                    style={formScreenStyle.otpInputStyle}
                                    autoFocus={true}
                                    returnKeyType="next"
                                    ref={ref_input[0]}
                                    onChangeText={text => focusNext(text, 0)}
                                    onKeyPress={e => focusPrev(e.nativeEvent.key, 0)}
                                />
                                <TextInput
                                    mode="flat"
                                    selectionColor={Colors.primaryColor}
                                    underlineColorAndroid="transparent"
                                    textAlign='center'
                                    maxLength={1}
                                    keyboardType='numeric'
                                    style={formScreenStyle.otpInputStyle}
                                    ref={ref_input[1]}
                                    onChangeText={text => focusNext(text, 1)}
                                    onKeyPress={e => focusPrev(e.nativeEvent.key, 1)}
                                />
                                <TextInput
                                    mode="flat"
                                    selectionColor={Colors.primaryColor}
                                    underlineColorAndroid="transparent"
                                    textAlign='center'
                                    maxLength={1}
                                    keyboardType='numeric'
                                    style={formScreenStyle.otpInputStyle}
                                    ref={ref_input[2]}
                                    onChangeText={text => focusNext(text, 2)}
                                    onKeyPress={e => focusPrev(e.nativeEvent.key, 2)}
                                />
                                <TextInput
                                    mode="flat"
                                    selectionColor={Colors.primaryColor}
                                    underlineColorAndroid="transparent"
                                    textAlign='center'
                                    maxLength={1}
                                    keyboardType='numeric'
                                    style={formScreenStyle.otpInputStyle}
                                    ref={ref_input[3]}
                                    onChangeText={text => focusNext(text, 3)}
                                    onKeyPress={e => focusPrev(e.nativeEvent.key, 3)}
                                />
    
                            </View>
                        </ScrollView>
                </View>
            </SafeAreaView >
        )
    }
    
    export default OTP;
    
    import React, { useState, useRef } from 'react';
    
    function Header(props) {
    
      const [state , setState] = useState({
            phone_number:"",
            code_one:'',
            code_two:'',
            code_three:'',
            code_four:'',
            submitted:false,
    
      })
    
       const codeOneInput = useRef(null);
       const codeTwoInput = useRef(null);
       const codeThreeInput = useRef(null);
       const codeFourInput = useRef(null);
    
       const handleCodeChange = (e) => {
            const {id , value} = e.target
            if(value.length < 2){
                setState(prevState => ({
                    ...prevState,
                    [id] : value
                }))
                if(id=='code_one' && value.length >0){
                    codeTwoInput.current.focus();
                }
                if(id=='code_two'  && value.length >0){
                    codeThreeInput.current.focus();
                }
                if(id=='code_three'  && value.length >0){
                    codeFourInput.current.focus();
                }
            }
        }
    
        const sendCodeToServer = () => {
    
             setState(prevState => ({
                    ...prevState,
                    submitted : true,
              }))
      let codeEnteredByUser = state.code_one + state.code_two + state.code_three + state.code_four
    
            axios.post(API_BASE_URL, {code:codeEnteredByUser})
            .then(function (response) {
                console.log(response)
            })
    
       }
    
       return(
            <>
    
               <div className="are">
                     <div className="POP-INN-INPUT">
                                            <input type="text" id="code_one" ref={codeOneInput}    value={state.code_one}  onChange={handleCodeChange} autoFocus/>
                                            <input type="text" id="code_two"  ref={codeTwoInput}  value={state.code_two} onChange={handleCodeChange}/>
                                            <input type="text" id="code_three"  ref={codeThreeInput} value={state.code_three}  onChange={handleCodeChange}/>
                                            <input type="text" id="code_four" ref={codeFourInput}  value={state.code_four}  onChange={handleCodeChange}/>
                                        </div>
    
                <button disabled={state.submitted} onClick={sendCodeToServer}>
       
        </div>
    
           </>
        )
    }
    export default
    
    import React, { useRef } from 'react'
    ...
    
    
    const MyFormComponent = () => {
    
      const ref_input2 = useRef();
    
      return (
        <>
          <TextInput
            placeholder="Input1"
            autoFocus={true}
            returnKeyType="next"
            onSubmitEditing={() => ref_input2.current.focus()}
          />
          <TextInput
            placeholder="Input2"
            returnKeyType="done"
            refInner={ref_input2}
            onSubmitEditing={/* Do something! */}
          />
        </>
      )
    }
    
    export function CustomTextInput(props) {
      <Input
            ref={props.refInner}
            {...props}
      />
    }