Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to autofocus next TextInput on react-native

I'm trying to create a passcode protected screen. The screen will uses 4 numeric input as the passcode.

The way I'm doing this is create a TextInput Component and call it 4 times in my main screen.

The problem I'm having is the TextInputs will not focus on the next one as I type the value of the previous TextInput.

I'm using refs for all PasscodeTextInput component (I've been informed that it is a legacy method but I do not know any other way, alas).

Tried this method(without creating my own component), no luck too. 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 };

Update 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);
like image 830
J.Doe Avatar asked Feb 21 '17 15:02

J.Doe


People also ask

How to auto focus text input in React Native App?

By default when react native app starts then there is no TextInput component will be focus but we can manually-dynamically focus any TextInput present in react native app using autoFocus = {true} prop. This prop would allow us to automatically focus/selects any TextInput on application starts time.

How to select-focus the textinput on App start time in Android?

Create 1st TextInput component in Root View. Now we would use the autoFocus = {true} prop in this TextInput. Using this prop it will by default automatically selects-focus the TextInput on app starts time. We would use another prop returnKeyType = {“next”} in TextInput. This prop will show the Next Button on Keypad screen.

How to enable auto focus on textinput in AutoCAD?

Enabling Auto Focus using autoFocus = {true} prop in TextInput. Showing Next button on Keypad ( Both Android & iOS devices ). Auto Select next TextInput on Next button Press. 1. Import StyleSheet, View and TextInput component in your project.

Is it possible to call focus() on a text input node?

As of React Native 0.36, calling focus () (as suggested in several other answers) on a text input node isn't supported any more. Instead, you can use the TextInputState module from React Native. I created the following helper module to make this easier:


2 Answers

There is a defaultProp for TextInput where one can focus after component mounted.

autoFocus

If true, focuses the input on componentDidMount, the default value is false. for more information please read the related Docs.

UPDATE

After componentDidUpdate it won't work properly. In that case, one can use ref to focus programmatically.

like image 166
Mukundhan Avatar answered Oct 20 '22 18:10

Mukundhan


You cannot forward the ref to <TextInput> using that way because ref is one of the special props. Thus, calling this.refs.passcode2 will return you <PasscodeTextInput> instead.

Try change to the following to get the ref from <TextInput>.

PasscodeTextInput.js

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

  ...

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

Then, assign the inputRef from <PasscodeTextInput> to a variable and use focus() to switch focus (it is not deprecated as of 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() prevents focus is switched when trying to clear the old passcode and enter a new one.

like image 21
max23_ Avatar answered Oct 20 '22 20:10

max23_