[英]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.