web-dev-qa-db-ja.com

React Native: "next"キーボードボタンを押した後に次のTextInputを選択する方法

次のように2つのTextInputフィールドを定義しました。

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

しかし、私のキーボードの「次へ」ボタンを押した後、私の反応ネイティブアプリは2番目のTextInputフィールドにジャンプしません。どうすればそれを達成できますか?

ありがとうございます。

126
andreaswienes

前のTextInputTextInputがトリガーされたときに、2番目のonSubmitEditingフォーカスを設定します。

これを試して

  1. secondへのRefの追加TextInput
    ref={(input) => { this.secondTextInput = input; }}

  2. フォーカス関数を最初のTextInputのonSubmitEditingイベントにバインドします。
    onSubmitEditing={() => { this.secondTextInput.focus(); }}

  3. キーボードのちらつきを防ぐために、blurOnSubmitをfalseに設定することを忘れないでください。
    blurOnSubmit={false}

すべて完了したら、これは次のようになります。

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

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

あなたはこれをすることができます 参照を使用せずに 。参照は 壊れやすいコード につながる可能性があるので、このアプローチが好ましいです。 Reactのドキュメント は、可能な限り他の解決策を見つけることをお勧めします。

Reactを使っていくつかのアプリをプログラムしていないのであれば、あなたの最初の傾向は通常、refsを使ってアプリ内で「問題を起こす」ことを試みることです。その場合は、少し時間をかけて、コンポーネント階層のどこで状態を所有するのかについて、もっと批判的に考えてください。多くの場合、その状態を「所有する」ための適切な場所が階層の上位レベルにあることが明らかになります。状態をそこに置くことは、しばしば「物事を起こさせる」ために参照を使用するという欲求を排除します - 代わりに、データフローは通常あなたの目標を達成するでしょう。

代わりに、状態変数を使用して2番目の入力フィールドにフォーカスします。

  1. 支柱としてDescriptionInputに渡す状態変数を追加します。

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  2. この状態変数をtrueに設定するハンドラメソッドを定義します。

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  3. TitleInputにenter/nextを送信する/押すと、handleTitleInputSubmitが呼び出されます。これはfocusDescriptionInputをtrueに設定します。

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  4. DescriptionInputfocus propは、focusDescriptionInput状態変数に設定されています。そのため、(ステップ3で)focusDescriptionInputが変更されると、DescriptionInputfocus={true}で再レンダリングされます。

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

Refはより脆弱なコードにつながる可能性があるので、これはrefの使用を避けるための良い方法です:)

編集:focusに応答させるためにReact Native TextInputをいくつかの追加された小道具とメソッドでラップする必要があることを指摘してくれた@LaneRettigのh/t:

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

    static defaultProps = { 
        focus: false,
    } 

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

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

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

React Native 0.36以降、テキスト入力ノードでfocus()を呼び出すこと(他のいくつかの回答で示唆されているように)は、もうサポートされません。代わりに、React NativeのTextInputStateモジュールを使うことができます。これを簡単にするために、次のようなヘルパーモジュールを作成しました。

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

その後、focusTextInputの任意の "ref"に対してTextInput関数を呼び出すことができます。例えば:

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

これを行う小さなライブラリを作成しました。ラッピングビューを置き換えて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/

18
zackify

React-native 0.45.1の使用ユーザー名TextInputでリターンキーを押した後、パスワードTextInputにフォーカスを設定しようとしたときにも問題が発生しました。

SOでトップクラスの解決策のほとんどを試した後、私は自分のニーズを満たすgithub上の解決策を見つけました: 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>
        )
    }
}
11
kuhr

私はRN 0.50.3でこれが可能です

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

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

This.PasswordInputRef。_ root。focus()が表示されます。

8
Wishmaster

偶然 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

7
Lane Rettig

これが私が達成した方法です。そして以下の例はReact 16.3で導入されたReact.createRef()APIを使用しています。

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

これはあなたに役立つと思います。

6

従来の 文字列参照の代わりにコールバック参照を使用する:

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

私のシナリオは、<CustomBoladonesTextInput />で、RNをラップ<TextInput />です。

私は以下のようにこの問題を解決しました:

私の形は次のようになります。

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

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

CustomBoladonesTextInputのコンポーネント定義では、次のようにrefFieldを内部のrefプロップに渡します。

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

そして、やあ。戻ってきたすべてが再び動作します。お役に立てれば

3

React NativeのGitHub問題でこの解決策を試してください。

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

TextInputコンポーネントにはref propを使用する必要があります。
次に、2番目のTextInput参照にフォーカスを移すonSubmitEditing propで呼び出される関数を作成する必要があります。

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

あなたのTextInputが別のコンポーネントの中にある場合に受け入れられる解決策が機能するためには、refから親コンテナへの参照を "ポップ"する必要があります。

// 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
<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();
}
2
Saloni Parikh

TextInputの中でタブをキャプチャする方法があります。ハッキーですが、 何もない よりも優れています。

\tをチェックしながら、新しい入力値と古い入力値を比較するonChangeTextハンドラを定義します。見つかった場合は、@ boredgamesのようにフィールドを進めます。

変数usernameがusernameの値を含み、setUsernameがストア内でそれを変更するアクション(コンポーネント状態、reduxストアなど)をディスパッチすると仮定すると、次のようにします。

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

あなたのコンポーネントで:

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

注: NativeBase'Library 'Input のTextInputへの参照であるため、私は._rootを使用しました。

そしてあなたのテキスト入力でこのように

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


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

NativeBaseをUIコンポーネントとして使用している場合は、このサンプルを使用できます。


         <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

ここでは、:focusプロパティを持つ入力コンポーネント用の試薬溶液です。

この小道具が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]))}))

https://Gist.github.com/Knotschi/6f97efe89681ac149113ddec4c396cc5

0
Knotschi