我目前正在为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>
);
}
焦点功能旨在将下一个输入焦点放在该索引上,但这似乎不起作用,但是样式发生了变化。我该怎么办?谢谢
我建议使用单个hidden 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()将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