2017-02-21 199 views
2

我试图创建一个密码保护屏幕。屏幕将使用4位数字输入作为密码。如何自动对焦反应本机上的下一个TextInput

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

我遇到的问题是TextInputs将不会专注于下一个,因为我键入以前的TextInput的值。

我使用所有PasscodeTextInput组件的参考(我已被告知它是一个传统的方法,但我不知道任何其他方式,唉)。

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

Image

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

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

更新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); 
+0

http://stackoverflow.com/questions/32748718/react-native-how-to-select-the-next-textinput-after-pressing-the-next-keyboar这里是信息。希望这可以帮助。 –

+0

@UjjwalNepal focus()方法已被弃用......,并且在0.40之后,mitch的答案是不可用的http://stackoverflow.com/a/41201939/5809351 –

+0

我想你可以避免在父项中有状态,只要在'componentDidMount'中做第一个输入的焦点,你的'onTextChanged'方法可以看起来像这样'if t == 1 or 2 or 3 then then focus the t + 1'input' – Igorsvee

回答

3

你不能用ref转换为<TextInput>,因为refspecial props之一。因此,致电this.refs.passcode2将返回您<PasscodeTextInput>

尝试更改以下以从<TextInput>获取ref

PasscodeTextInput.js

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

    ... 

    return (
    <View> 
     <TextInput 
     ref={(r) => { inputRef && inputRef(r) }} 
     ... 
     /> 
    </View> 
    ... 
); 
} 

然后,分配从<PasscodeTextInput>inputRef给一个变量,并使用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 }} /> 
); 

P.S:event && this.passcode2.focus()防止焦点试图清除旧密码,然后输入一个新的时切换。

+0

这是神奇的。谢谢! :) –

+0

@ J.doe:感谢代码。您是否删除了删除按键? – djk

1

我认为这个问题是onSubmitEditing是当你点击“返回”或“ENTER”键常规键盘上......有不是键盘上的那些按钮之一。

假设你希望每个输入只有一个字符,你可以看看onChangeText,然后检查是否有文本长度为1,并呼吁重点如果长度确实是1

+0

我以为是这样,我对代码做了一些修改,但它仍然不会工作 –

1

可以使用对焦方法onChangeText为杰森说,除了增加maxLength={1}可以让你跳到下一个输入,而不检查添加什么。 (刚注意到它的已弃用,但仍然这是我如何解决我的问题,并应该做的很好,直到v0.36,并且这link解释如何更新弃用的功能)。

<TextInput 
    ref="first" 
    style={styles.inputMini} 
    maxLength={1} 
    keyboardType="numeric" 
    returnKeyType='next' 
    blurOnSubmit={false} 
    placeholderTextColor="gray" 
    onChangeText={(val) => { 
     this.refs['second'].focus() 
    }} 
    /> 
    <TextInput 
    ref="second" 
    style={styles.inputMini} 
    maxLength={1} 
    keyboardType="numeric" 
    returnKeyType='next' 
    blurOnSubmit={false} 
    placeholderTextColor="gray" 
    onChangeText={(val) => { 
    this.refs['third'].focus() 
    }} 
    /> 
    ... 

请注意,我用的裁判不建议使用过,但我刚刚复制的代码,因为我可以向你保证,正在当年(希望现在的工作太)。

最后,这种类型的实现的主要问题是,一旦您尝试使用退格删除数字,您的焦点将跳转到下一个数字,导致严重的UX问题。但是,您可以听取退格键输入并执行一些不同的操作,而不是专注于下一个输入。所以我会在这里留下一个link供你进一步调查,如果你选择使用这种类型的实现。

哈克解决先前描述的问题:如果你检查什么在onChangeText道具进入做任何事情之前,你可以跳转到下一个输入,如果该值是一个,否则(这是一个退格键),跳回来。 (刚想出这个主意,我没有尝试过。)

2

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

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

此TextInput从用户处接受输入,但实际上看不到,因为每个字符都是输入的,我们将输入的文本呈现为一系列简单的视图/文本元素,风格与上面的屏幕非常相似。

这种方法对我们来说很合适,不需要管理旁边要重点关注的'下一个'或'以前的'TextInput。

+0

你能提供一些代码吗? – Dlucidone

相关问题