web-dev-qa-db-de.com

React Native: Wie wählt man den nächsten TextInput aus, nachdem die "nächste" Tastaturtaste gedrückt wurde?

Ich habe zwei TextInput-Felder wie folgt definiert:

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

Nachdem Sie auf der Tastatur die Schaltfläche "Weiter" gedrückt haben, springt meine reagierende Anwendung nicht zum zweiten TextInput-Feld. Wie kann ich das erreichen?

Vielen Dank!

113
andreaswienes

Setzen Sie den zweiten TextInput Fokus, wenn der TextInput des vorherigen onSubmitEditing ausgelöst wird.

Versuche dies

  1. Hinzufügen eines Verweises zu zweiter Texteingang
    ref={(input) => { this.secondTextInput = input; }}

  2. Binden Sie die Fokusfunktion an das onSubmitEditing-Ereignis von first TextInput.
    onSubmitEditing={() => { this.secondTextInput.focus(); }}

  3. Denken Sie daran, blurOnSubmit auf false zu setzen, um ein Flackern der Tastatur zu vermeiden.
    blurOnSubmit={false}

Wenn alles fertig ist, sollte es so aussehen.

<TextInput
    placeholder = "FirstTextInput"
    returnKeyType = { "next" }
    onSubmitEditing={() => { this.secondTextInput.focus(); }}
    blurOnSubmit={false}
/>

<TextInput
    ref={(input) => { this.secondTextInput = input; }}
    placeholder = "secondTextInput"
/>
248
boredgames

Sie können dies tun, ohne refs zu verwenden. Dieser Ansatz wird bevorzugt, da Referenzen zu fragile Code führen können. Die React docs raten, wenn möglich andere Lösungen zu finden: 

Wenn Sie nicht mehrere Apps mit React programmiert haben, wird Ihre erste Die Neigung besteht in der Regel darin, zu versuchen, Refs zu verwenden, um "Dinge zu machen. Wenn dies der Fall ist, nehmen Sie sich einen Moment Zeit und denken Sie mehr darüber nach kritisch darüber, wo sich der Staat in der Komponente befinden soll Hierarchie. Oft wird klar, dass der richtige Ort, um diese .__ zu "besitzen". Zustand ist auf einer höheren Ebene in der Hierarchie. Den Zustand dort setzen beseitigt oft den Wunsch, Refs zu verwenden, um "Dinge passieren zu lassen" – Stattdessen wird der Datenfluss normalerweise Ihr Ziel erreichen.

Stattdessen verwenden wir eine Zustandsvariable, um das zweite Eingabefeld zu fokussieren.

  1. Fügen Sie eine Zustandsvariable hinzu, die wir der DescriptionInput als Requisite übergeben:

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  2. Definieren Sie eine Handler-Methode, die diese Zustandsvariable auf true setzt:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  3. Wenn Sie auf der Variablen TitleInput Enter/next drücken, rufen wir handleTitleInputSubmit auf. Dies setzt focusDescriptionInput auf true.

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  4. Die Variable DescriptionInput der Variable focus ist auf unsere Zustandsvariable focusDescriptionInput gesetzt. Wenn sich focusDescriptionInput ändert (in Schritt 3), wird DescriptionInput mit focus={true} erneut gerendert.

    <TextInput
       style = {styles.descriptionInput}          
       multiline = {true}
       maxLength = {200}
       placeholder = "Description" 
       focus={this.state.focusDescriptionInput}
    />
    

Dies ist ein guter Weg, um die Verwendung von Refs zu vermeiden, da Refs zu fragilerem Code führen kann :)

EDIT: h/t an @LaneRettig für den Hinweis, dass Sie den React Native TextInput mit einigen hinzugefügten Requisiten und Methoden einpacken müssen, damit er auf focus reagiert:

    // Props:
    static propTypes = { 
        focus: PropTypes.bool,
    } 

    static defaultProps = { 
        focus: false,
    } 

    // Methods:
    focus() {
        this._component.focus(); 
    } 

    componentWillReceiveProps(nextProps) {
        const {focus} = nextProps; 

        focus && this.focus(); 
    }
44
Stedman Blake

Ab React Native 0.36 wird der Aufruf von focus() (wie in mehreren anderen Antworten vorgeschlagen) für einen Texteingabeknoten nicht mehr unterstützt. Stattdessen können Sie das TextInputState-Modul von React Native verwenden. Ich habe das folgende Hilfsmodul erstellt, um dies zu erleichtern:

// 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)
  }
}

Sie können dann die focusTextInput-Funktion für jede "ref" einer TextInput aufrufen. Zum Beispiel:

...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...
25
Mitch

Ich habe eine kleine Bibliothek erstellt, die dies ausführt. Es ist keine Codeänderung erforderlich, außer die Umbruchansicht und den Import von TextInput zu ersetzen: 

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

Ausführlich hier erklärt: https://zach.codes/autofocus-inputs-in-react-native/

17
zackify

Bei der Verwendung von react-native 0.45.1 sind auch Probleme beim Versuch aufgetreten, den Fokus auf ein Passwort zu setzen.

Nachdem ich die meisten der bestbewerteten Lösungen hier auf SO) ausprobiert hatte, fand ich eine Lösung für Github, die meine Anforderungen erfüllte: https://github.com/shoutem/ui/issues/ 44 # issuecomment-290724642

Etwas zusammenfassen:

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)}
            />
        );
    }
}

Und dann benutze ich es so:

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>
        )
    }
}
11
kuhr

Wenn Sie tcomb-form-native so wie ich bin, können Sie dies auch tun. Hier ist der Trick: Anstatt die Requisiten der TextInput direkt einzustellen, tun Sie dies über options. Sie können sich auf die Felder des Formulars beziehen als:

this.refs.form.getComponent('password').refs.input.focus()

Das Endprodukt sieht also ungefähr so ​​aus:

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>
    );
  },
});

(Dank an remcoanker für die Veröffentlichung der Idee: https://github.com/gcanti/tcomb-form-native/issues/96 )

7
Lane Rettig

Für mich auf RN 0.50.3 ist dies auf folgende Weise möglich:

<TextInput 
  autoFocus={true} 
  onSubmitEditing={() => {this.PasswordInputRef._root.focus()}} 
/>

<TextInput ref={input => {this.PasswordInputRef = input}} />

Sie müssen this.PasswordInputRef. _root . Focus () sehen.

7
Wishmaster

So habe ich es erreicht. Das folgende Beispiel hat die in React 16.3 eingeführte React.createRef () - API verwendet.

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>
    );
  }
}

Ich denke das wird dir helfen.

4

Callback-Refs anstelle der Legacy String-Refs verwenden: 

<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}
/>
3
fagerbua

Versuchen Sie diese Lösung bei GitHub-Problemen von React Native.

https://github.com/facebook/react-native/pull/2149#issuecomment-129262565

Sie müssen das ref prop für die TextInput-Komponente verwenden.
Dann benötigen Sie eine Funktion, die für onSubmitEditing prop aufgerufen wird und den Fokus auf den zweiten TextInput-Ref verlagert. 

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>
        );
    }
});
3
APAquino

Damit die akzeptierte Lösung funktioniert, wenn sich Ihre TextInput in einer anderen Komponente befindet, müssen Sie die Referenz von ref in den übergeordneten Container platzieren.

// 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}/>
}
2
Eldelshell

Mein Szenario ist <CustomBoladonesTextInput /> Ein RN umschließen <TextInput /> .

Ich habe dieses Problem wie folgt gelöst:

Mein Formular sieht so aus:

  <CustomBoladonesTextInput 
      onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
      returnKeyType="next"
      ... />

  <CustomBoladonesTextInput 
       ref={ref => this.customInput2 = ref}
       refInner="innerTextInput2"
       ... />

In der Komponentendefinition von CustomBoladonesTextInput übergebe ich das refField wie folgt an den inneren Ref-Prop:

   export default class CustomBoladonesTextInput extends React.Component {
      render() {        
         return (< TextInput ref={this.props.refInner} ... />);     
      } 
   }

Und voila. Alles wieder funktionsfähig. Hoffe das hilft

2
<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%', }} />

und Methode hinzufügen

focusNextField(nextField) {
    this.refs[nextField].focus();
}
2
Saloni Parikh

Es gibt eine Möglichkeit, tabs in einer TextInput zu erfassen. Es ist hackig, aber besser als nichts .

Definieren Sie einen onChangeText-Handler, der den neuen Eingabewert mit dem alten vergleicht und nach einem \t sucht. Wenn eines gefunden wird, bewegen Sie das Feld wie von @boredgames gezeigt vor

Wenn die Variable username den Wert für den Benutzernamen enthält und setUsername eine Aktion auslöst, um sie im Speicher (Komponentenstatus, Redux-Store usw.) zu ändern, gehen Sie folgendermaßen vor:

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} />
    )
  }
}
1
marius

in Ihrer Komponente:

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

Hinweis: Ich habe ._root verwendet, da es sich um einen Bezug zu TextInput in NativeBase'Library 'handelt. Eingabe

und in Ihren Texteingaben so

<TextInput
         onSubmitEditing={() => {
                          this.focusNextField('two');
                          }}
         returnKeyType="next"
         blurOnSubmit={false}/>


<TextInput      
         ref={input => {
              this.inputs['two'] = input;
                        }}/>
1
amorenew

Wenn Sie NativeBase als UI-Komponenten verwenden, können Sie dieses Beispiel verwenden


         <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>```
0

Hier eine Reagenzlösung für eine Eingabekomponente mit der Eigenschaft: focus.

Das Feld wird so lange fokussiert, wie diese Stütze auf wahr gesetzt ist, und nicht fokussiert sein, solange dies falsch ist.

Leider muss für diese Komponente ein: ref definiert sein. Ich konnte keine andere Möglichkeit finden, .focus () darauf aufzurufen. Ich freue mich über Vorschläge.

(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

0
Knotschi