2017-02-21 9 views
2

Я пытаюсь создать защищенный паролем экран. На экране будет использоваться 4 числовых ввода в качестве кода доступа.Как автофокусировать следующий TextInput на native-native

Способ, которым я это делаю, это создать компонент TextInput и называть его 4 раза на главном экране.

Проблема, с которой я столкнулась, это TextInputs не будет фокусироваться на следующем, поскольку я набираю значение предыдущего TextInput.

Я использую refs для всех компонентов 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() устарел ..., и ответ от mitch не может быть использован после 0.40 http://stackoverflow.com/a/41201939/5809351 –

+0

Я полагаю, вы можете вообще не иметь состояния в родительском , просто сделайте фокус 1-го ввода в 'componentDidMount', и ваш метод' onTextChanged' может выглядеть примерно так: 'if t == 1 или 2 или 3, затем сфокусируйте t + 1-й вход' – Igorsvee

ответ

3

Вы не можете направить ref в <TextInput> используя этот путь, потому что ref является одним из special props. Таким образом, при вызове this.refs.passcode2 вместо вас вы получите <PasscodeTextInput>.

Чтобы получить ref, необходимо выполнить следующие действия: <TextInput>.

PasscodeTextInput.js

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

    ... 

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

Затем назначьте inputRef от <PasscodeTextInput> переменной и использовать focus() для переключения фокуса (не рекомендуется в качестве РН 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 когда вы нажимаете клавишу «возврат» или «введите» клавишу на обычной клавиатуре ... есть не является одной из этих кнопок на клавиатуре.

Предполагая, что вы хотите, чтобы каждый вход только один символ, вы можете посмотреть на 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, чтобы вы могли продолжить расследование, если вы решите использовать этот тип реализации.

Hacky Решение Ранее Описанная выпуска: Если вы отметите, что вошел в onChangeText реквизита, прежде чем делать что-либо, вы можете переходить к следующему входу, если значение является число, остальное (это забой), прыжок назад. (Только пришел с этой идеей, я не пробовал.)

2

мы обрабатывали этот стиль экрана с другим подходом.

Вместо того, чтобы управлять четырьмя отдельными текстовыми вводами и управлять навигацией по каждому из них (а затем обратно, когда пользователь удаляет символ), у нас есть один экран TextInput, но он невидим (т. Е. 0px x 0px) в ширину который имеет фокус, максимальную длину и конфигурацию клавиатуры и т. д.

Этот TextInput принимает входные данные от пользователя, но на самом деле не может быть замечен, так как каждый символ вводится, мы визуализируем введенный текст как простой ряд элементов View/Text , очень похож на ваш экран выше.

Этот подход сработал для нас без необходимости управлять тем, с чем следует фокусироваться рядом с «следующим» или «предыдущим» TextInput.

+0

Вы можете указать код? – Dlucidone

Смежные вопросы