2017-02-21 83 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

相關問題