渐进地聚焦TextInput响应本机

问题描述 投票:0回答:2

我目前正在为React Native应用创建一个4位数的otp(一次性密码)视图,当我在前一个输入中键入数字时,我需要TextInput逐步集中注意力。

我已经能够进行样式更改(没有焦点),但是焦点不会随之更改,并且当我输入另一个数字时,应用程序崩溃。

[我想要这样,当我在第一个输入上键入内容时,焦点移到下一个TextInput上,依此类推,在最后一个输入上,焦点集中在提交上。

我该如何处理?

下面是我的代码

组件

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, ScrollView, View, Alert, Image } from 'react-native';
import { SimpleLinearGradientButton } from '../../components/Buttons';
import { SimpleCard } from '../../components/Cards';

export default function(props) {
  const [otp, setOtp] = useState([]);
  const [isFocused, setIsFocused] = useState({ focused: true, index: 0 });

  const inputs = Array(4).fill(0);

 function renderInputs() {
    return inputs.map((input, index) => {
      return (
        <TextInput
          style={
            isFocused.focused && index === isFocused.index
              ? styles.inputFieldsFocused
              : styles.inputFields
          }
          key={index}
          keyboardType={'numeric'}
          onChange={focus}
        ></TextInput>
      );
    });
  }

  function focus(e) {
    setOtp(otp.concat(this.value));
    setIsFocused({ focused: true, index: isFocused.index + 1 });
    isFocused.index ? e.focus() : null;
  }

  return (
    <ScrollView contentContainerStyle={styles.content}>
      <View>
        <Image
          style={styles.image}
          source={require('../../../assets/images/verification.png')}
        />
      </View>
      <View>
        <Text>Verification</Text>
        <Text>
          Enter the 4 digit sent to your email address
        </Text>
      </View>
      <View>
        <SimpleCard>
          <>{renderInputs()}</>
        </SimpleCard>
        <SimpleLinearGradientButton
              title="Submit"
            />
          </View>
        </ScrollView>
      );
    }

焦点功能旨在将下一个输入焦点放在该索引上,但这似乎不起作用,但是样式发生了变化。我该怎么办?谢谢

javascript reactjs react-native autofocus
2个回答
0
投票

我建议使用单个hidden TextInput,并根据输入的值以简单的View -s呈现数字。我认为没有理由为4位数字代码使用不同的输入。

但是,如果需要使用不同的输入,则必须以命令方式(使用refs)控制其焦点状态。请参见focus()方法。此方法也有一些错误(https://github.com/facebook/react-native/issues/19366

在此处查看文档https://facebook.github.io/react-native/docs/textinput


0
投票

tl [dr设置textInput的maxLength为1,使用refs和focus()将onChnageText回调更改为下一个textInput

这是一个易于理解的简单实现。您可以更好地减少代码。而且我猜您应该实现Backspace来清除文本并返回到先前的textinput。我使用onKeyPress属性来实现。

import React, { Component } from 'react';
import { Text, View, StyleSheet, TextInput } from 'react-native';
import Constants from 'expo-constants';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      one: '',
      two: '',
      three: '',
      oneFocus: false,
      twoFocus: false,
      threeFocus: false,
    };
  }

  componentDidMount() {
    this.refs.one.focus();
  }

    handleChangeTextOne = (text) => {
      this.setState({ one: text }, () => { if (this.state.one) this.refs.two.focus(); });
    }
  handleChangeTextTwo = (text) => {
    this.setState({ two: text }, () => { if (this.state.two) this.refs.three.focus(); });
  }
  handleChangeTextThree = (text) => {
    this.setState({ three: text });
  }

    backspace = (id) => {
      if (id === 'two') {
        if (this.state.two) { this.setState({ two: '' }); } else if (this.state.one) { this.setState({ one: '' }); this.refs.one.focus(); }
      } else if (id === 'three') {
        if (this.state.three) { this.setState({ three: '' }); } else if (this.state.two) { this.setState({ two: '' }); this.refs.two.focus(); }
      }
    }

    render() {
      const { oneFocus, twoFocus, threeFocus } = this.state;
      const oneStyle = {
        borderBottomColor: oneFocus ? 'red' : 'black',
        borderBottomWidth: oneFocus ? 2 : 1,
      };
      const twoStyle = {
        borderBottomColor: twoFocus ? 'red' : 'black',
        borderBottomWidth: twoFocus ? 2 : 1,
      };
      const threeStyle = {
        borderBottomColor: threeFocus ? 'red' : 'black',
        borderBottomWidth: threeFocus ? 2 : 1,
      };
      return (
        <View style={styles.container}>
          <View style={styles.inputcontainer}>
            <TextInput
              ref='one'
              style={[styles.textInput, { ...oneStyle }]}
              autoCorrect={false}
              autoCapitalize='none'
              keyboardType='number-pad'
              caretHidden
              onFocus={() => this.setState({ oneFocus: true })}
              onBlur={() => this.setState({ oneFocus: false })}
              maxLength={1}
              onChangeText={(text) => { this.handleChangeTextOne(text); }}
              value={this.state.one}
            />
            <TextInput
              ref='two'
              onKeyPress={({ nativeEvent }) => (
                nativeEvent.key === 'Backspace' ? this.backspace('two') : null
              )}
              style={[styles.textInput, { ...twoStyle }]}
              autoCorrect={false}
              autoCapitalize='none'
              maxLength={1}
              onFocus={() => this.setState({ twoFocus: true })}
              onBlur={() => this.setState({ twoFocus: false })}
              caretHidden
              keyboardType='number-pad'
              onChangeText={(text) => { this.handleChangeTextTwo(text); }}
              value={this.state.two}
            />
            <TextInput
              ref='three'
              onKeyPress={({ nativeEvent }) => (
                nativeEvent.key === 'Backspace' ? this.backspace('three') : null
              )}
              style={[styles.textInput, { ...threeStyle }]}
              autoCorrect={false}
              autoCapitalize='none'
              onFocus={() => this.setState({ threeFocus: true })}
              onBlur={() => this.setState({ threeFocus: false })}
              maxLength={1}
              caretHidden
              keyboardType='number-pad'
              onChangeText={(text) => { this.handleChangeTextThree(text); }}
              value={this.state.four}
            />
          </View>
        </View>
      );
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  }, 
  inputcontainer: {
    height: '5%',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    paddingHorizontal: '20%',
    marginBottom: '2%',
  }, 
  textInput: {
    fontSize: 22,
    textAlign: 'center',
    paddingVertical: 0,
    paddingHorizontal: 0,
    width: '12%',
  },
});

零食运行:https://snack.expo.io/@legowtham/otp-textinput-example-react-native

© www.soinside.com 2019 - 2024. All rights reserved.