如何在react-native上自动对焦下一个TextInput

J.D*_*Doe 7 javascript facebook textinput react-native

我正在尝试创建一个受密码保护的屏幕.屏幕将使用4个数字输入作为密码.

我这样做的方法是创建一个TextInput组件,并在我的主屏幕中调用它4次.

我遇到的问题是当我键入前一个TextInput的值时,TextInputs不会关注下一个.

我正在为所有PasscodeTextInput组件使用refs(我已被告知这是一种遗留方法,但我不知道其他任何方式,唉).

试过这个方法(没有创建我自己的组件),也没有运气. 方法

图片

index.ios.js

import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';

export default class ProgressBar extends Component {
  render() {
    const { centerEverything, container, passcodeContainer,  textInputStyle} = styles;
    return (
      <View style={[centerEverything, container]}>
        <View style={[passcodeContainer]}>
          <PasscodeTextInput
            autoFocus={true}
            ref="passcode1"
            onSubmitEditing={(event) => { this.refs.passcode2.focus() }} />
          <PasscodeTextInput
            ref="passcode2"
            onSubmitEditing={(event) => { this.refs.passcode3.focus() }} />
          <PasscodeTextInput
            ref="passcode3"
            onSubmitEditing={(event) => { this.refs.passcode4.focus() }}/>
          <PasscodeTextInput
            ref="passcode4" />
        </View>
      </View>
    );
  }
}

const styles = {
  centerEverything: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  container: {
    flex: 1,
    backgroundColor: '#E7DDD3',
  },
  passcodeContainer: {
    flexDirection: 'row',
  },
}

AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
Run Code Online (Sandbox Code Playgroud)

PasscodeTextInput.js

import React from 'react';
import {
  View,
  Text,
  TextInput,
  Dimensions
} from 'react-native';

const deviceWidth = require('Dimensions').get('window').width;
const deviceHeight = require('Dimensions').get('window').height;

const PasscodeTextInput = ({ ref, autoFocus, onSubmitEditing, onChangeText, value}) => {

  const { inputStyle, underlineStyle } = styles;

  return(
    <View>
      <TextInput
        ref={ref}
        autoFocus={autoFocus}
        onSubmitEditing={onSubmitEditing}
        style={[inputStyle]}
        maxLength={1}
        keyboardType="numeric"
        placeholderTextColor="#212121"
        secureTextEntry={true}
        onChangeText={onChangeText}
        value={value}
      />
      <View style={underlineStyle} />
    </View>
  );
}

const styles = {
  inputStyle: {
    height: 80,
    width: 60,
    fontSize: 50,
    color: '#212121',
    fontSize: 40,
    padding: 18,
    margin: 10,
    marginBottom: 0
  },
  underlineStyle: {
    width: 60,
    height: 4,
    backgroundColor: '#202020',
    marginLeft: 10
  }
}

export { PasscodeTextInput };
Run Code Online (Sandbox Code Playgroud)

更新1

index.ios.js

import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';

export default class ProgressBar extends Component {

  constructor() {
    super()
    this.state = {
      autoFocus1: true,
      autoFocus2: false,
      autoFocus3: false,
      autoFocus4: false,
    }
  }

  onTextChanged(t) { //callback for immediate state change
    if (t == 2) { this.setState({ autoFocus1: false, autoFocus2: true }, () => { console.log(this.state) }) }
    if (t == 3) { this.setState({ autoFocus2: false, autoFocus3: true }, () => { console.log(this.state) }) }
    if (t == 4) { this.setState({ autoFocus3: false, autoFocus4: true }, () => { console.log(this.state) }) }
  }

  render() {
    const { centerEverything, container, passcodeContainer, testShit, textInputStyle } = styles;
    return (
      <View style={[centerEverything, container]}>
        <View style={[passcodeContainer]}>
          <PasscodeTextInput
            autoFocus={this.state.autoFocus1}
            onChangeText={() => this.onTextChanged(2)} />
          <PasscodeTextInput
            autoFocus={this.state.autoFocus2}
            onChangeText={() => this.onTextChanged(3)} />
          <PasscodeTextInput
            autoFocus={this.state.autoFocus3}
            onChangeText={() => this.onTextChanged(4)} />
          <PasscodeTextInput
            autoFocus={this.state.autoFocus4} />
        </View>
      </View>
    );
  }
}

const styles = {
  centerEverything: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  container: {
    flex: 1,
    backgroundColor: '#E7DDD3',
  },
  passcodeContainer: {
    flexDirection: 'row',
  },
}

AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
Run Code Online (Sandbox Code Playgroud)

Muk*_*han 11

TextInput有一个defaultProp,可以在安装组件后对焦.

自动对焦

如果为true,则将输入聚焦在componentDidMount上,默认值为false.有关更多信息,请阅读相关文档.

UPDATE

之后componentDidUpdate它将无法正常工作.在这种情况下,可以使用ref编程方式进行聚焦.


max*_*23_ 6

您不能将其转发ref<TextInput>使用这种方式,因为它ref特殊的道具之一。因此,致电this.refs.passcode2<PasscodeTextInput>代替您返回。

尝试更改为以下,以获得ref<TextInput>

PasscodeTextInput.js

const PasscodeTextInput = ({ inputRef, ... }) => {

  ...

  return (
    <View>
      <TextInput
        ref={(r) => { inputRef && inputRef(r) }}
        ...
      />
    </View>
    ...
  );
}
Run Code Online (Sandbox Code Playgroud)

然后,将inputReffrom从分配给<PasscodeTextInput>变量并用于focus()切换焦点(从RN开始不推荐使用0.41.2)。

index.ios.js

return (
  <PasscodeTextInput
    autoFocus={true}
    onChangeText={(event) => { event && this.passcode2.focus() }} />

  <PasscodeTextInput
    inputRef={(r) => { this.passcode2 = r }}
    onChangeText={(event) => { event && this.passcode3.focus() }} />

  <PasscodeTextInput
    inputRef={(r) => { this.passcode3 = r }}
    onChangeText={(event) => { event && this.passcode4.focus() }} />

  <PasscodeTextInput
    inputRef={(r) => { this.passcode4 = r }} />
);
Run Code Online (Sandbox Code Playgroud)

PS:event && this.passcode2.focus()防止在尝试清除旧密码并输入新密码时切换焦点。


cra*_*erm 6

我们用不同的方法处理这种风格的屏幕。

我们没有管理 4 个单独的 TextInputs 并处理每个 TextInputs 的焦点导航(然后在用户删除字符时再次返回),我们在屏幕上有一个 TextInput 但不可见(即 0px x 0px)宽,它具有焦点, maxLength 和键盘配置等。

这个 TextInput 接受来自用户的输入但实际上不能被看到,因为每个字符都是输入的,我们将输入的文本呈现为一系列简单的 View/Text 元素,样式与上面的屏幕非常相似。

这种方法对我们来说效果很好,无需管理要关注的“下一个”或“上一个”TextInput。