繁体   English   中英

逐步关注 TextInput 响应本机

[英]Progressively focus TextInput 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>
      );
    }

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

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

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

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

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

这是一个易于理解的直接实现。 您可以更好地减少代码。 而且我猜你应该实现 Backspace 来清除文本并返回到以前的文本输入。 我使用 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM