ios native缺點 React Native:如何在按下“下一個”鍵盤按鈕後選擇下一個TextInput?



react native中文 (14)

我定義了兩個TextInput字段,如下所示:

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

但是在按下鍵盤上的“下一步”按鈕後,我的本機應用程序沒有跳轉到第二個TextInput字段。 我怎樣才能做到這一點?

謝謝!


Answer #1

如果您的 TextInput 位於另一個組件中,則可以使用已接受的解決方案,您需要將引用從“彈出”引用到父容器。

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

Answer #2

對我來說,RN 0.50.3可以用這種方式:

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

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

你必須看到這個.PasswordInputRef。 _root .focus()


Answer #3

使用react-native 0.45.1我在按用戶名TextInput上的返回鍵後嘗試將焦點設置為密碼TextInput時也遇到了問題。

在這裡嘗試了大多數評價最高的解決方案後,我在github上找到了滿足我需求的解決方案: https://github.com/shoutem/ui/issues/44#issuecomment-290724642https://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>
        )
    }
}

Answer #4

有一種方法可以捕獲 TextInput 選項卡 。 這是hacky,但總比 nothing

定義一個 onChangeText 處理程序,用於將新輸入值與舊輸入值進行比較,檢查 \t 。 如果找到一個,請按@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} />
    )
  }
}

Answer #5

我的場景是 <CustomBoladonesTextInput /> 包裝RN <TextInput />

我解決了這個問題如下:

我的表格如下:

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

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

在CustomBoladonesTextInput的組件定義中,我將refField傳遞給內部ref prop,如下所示:

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

瞧。 一切都恢復正常。 希望這可以幫助


Answer #6

你可以 不使用refs 來做到這一點。 這種方法是首選,因為refs可能導致 脆弱的代碼 React文檔 建議盡可能找到其他解決方案:

如果您還沒有使用React編寫多個應用程序,那麼您的第一個傾向通常是嘗試使用refs在您的應用程序中“讓事情發生”。 如果是這種情況,請花一點時間,更關鍵地考慮組件層次結構中應該擁有狀態的位置。 通常,很明顯,“擁有”該狀態的適當位置在層次結構中處於更高級別。 在那裡放置狀態通常消除了使用refs“讓事情發生”的任何願望 - 相反,數據流通常會實現你的目標。

相反,我們將使用狀態變量來聚焦第二個輸入字段。

  1. 添加一個我們將作為prop傳遞給 DescriptionInput 的狀態變量:

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
  2. 定義一個將此狀態變量設置為true的處理程序方法:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
  3. TitleInput 上提交/命中enter / next TitleInput ,我們將調用 handleTitleInputSubmit 。 這會將 focusDescriptionInput 設置為true。

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
  4. DescriptionInputfocus 道具設置為我們的 focusDescriptionInput 狀態變量。 因此,當 focusDescriptionInput 更改時(在步驟3中), DescriptionInput 將使用 focus={true} 重新呈現。

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

這是避免使用refs的好方法,因為refs會導致更脆弱的代碼:)

編輯:h / t到@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(); 
    }

Answer #7

當觸發前一個 TextInputonSubmitEditing 時,設置第二個 TextInput 焦點。

試試這個

  1. 將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"
/>

Answer #8

在React Native的GitHub問題上嘗試這個解決方案。

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

您需要為TextInput組件使用ref prop。
然後你需要創建一個在onSubmitEditing prop上調用的函數,該函數將焦點移動到第二個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>
        );
    }
});

Answer #9

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

然後,您可以在 TextInput 任何“ref”上調用 focusTextInput 函數。 例如:

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

Answer #10

在您的組件中:

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'輸入中的 TextInput的 引用

並在你的文字輸入這樣

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


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

Answer #11

如果您正好像我一樣使用 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/96https://github.com/gcanti/tcomb-form-native/issues/96


Answer #12

如果您使用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>

Answer #13

這裡是具有:focus屬性的輸入組件的試劑解決方案。

只要此prop為true,就會聚焦該字段,只要這是假的,就不會有焦點。

不幸的是這個組件需要有一個: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


Answer #14

使用回調引用而不是 legacy 字符串引用:

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




react-native