React Native不依赖第三方库实现PIN码自定义输入键盘求助
问题排查与修复方案
核心问题清单
- 直接修改state原始引用,未生成新数组实例,React无法检测到state变化,导致界面不更新
- 删除函数循环索引越界,从下标4(超出数组最大下标3)开始遍历,永远无法找到可删除的输入位
- 确认按钮(对勾图标)错误绑定了删除事件,未实现PIN码获取逻辑
- 输入位容器为空,未填充
*掩码字符,看不到输入状态 - 已填充/未填充输入位样式完全一致,无法直观区分输入进度
修复后完整代码
import React, { Component } from "react"; import { StyleSheet, Text, View, ImageBackground, TouchableOpacity, Image, } from "react-native"; import Theme from "../../utils/Theme"; // 已删除未使用的第三方库导入 const hRem = AppStore.screenHeight / 812; const wRem = AppStore.screenWidth / 375; class PinAuthentication extends Component { constructor(props) { super(props); this.state = { passcode: ["", "", "", ""], }; } onPressNumber = (num) => { // 生成新数组实例,避免直接修改原state const tempcode = [...this.state.passcode]; for (let i = 0; i < tempcode.length; i++) { if (tempcode[i] === "") { tempcode[i] = num; break; } } this.setState({ passcode: tempcode }); }; onPressCancel = () => { const tempcode = [...this.state.passcode]; // 修正索引边界,从数组最后一位开始遍历 for (let i = tempcode.length - 1; i >= 0; i--) { if (tempcode[i] !== "") { tempcode[i] = ""; break; } } this.setState({ passcode: tempcode }); }; // 新增确认提交函数,获取完整PIN码 onPressConfirm = () => { const fullPin = this.state.passcode.join(''); if (fullPin.length === 4) { console.log('获取到的4位PIN码:', fullPin); // 此处可扩展PIN校验、提交等业务逻辑 } else { console.log('请输入完整4位PIN码'); } }; render() { let numbers = [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }, { id: 8 }, { id: 9 }, { id: 10 }, { id: 0 }, { id: 11 }, ]; return ( <> <ImageBackground style={styles.container} source={require("../../assets/Images/SliderImages/Background02sc.png")} /> <View style={styles.headerStyle}> <TouchableOpacity> <Image style={styles.backButton} source={require("../../assets/Images/SliderImages/Icon/BackButton.png")} /> </TouchableOpacity> <View> <Text style={styles.pinText}>Set new PIN</Text> </View> </View> <View> <Text style={styles.pinConfirmationText}>Enter new PIN</Text> </View> <View style={styles.codeContainer}> {this.state.passcode.map((x, index) => { let codes = x !== "" ? styles.inputBox1 : styles.inputBox; return ( <View key={index} style={codes}> {/* 新增掩码显示 */} <Text style={styles.maskText}>{x ? "*" : ""}</Text> </View> ); })} </View> <View style={{ alignItems: "center", justifyContent: "center" }}> <View style={styles.numberContainer}> {numbers.map((num) => { return ( <React.Fragment key={num.id}> {num.id === 10 ? ( <TouchableOpacity onPress={this.onPressCancel} style={styles.number} > <Image style={styles.img} source={require("../../assets/Images/SliderImages/Icon/icons_cancel_last_digit.png")} /> </TouchableOpacity> ) : num.id === 11 ? ( <TouchableOpacity // 修正确认键绑定逻辑 onPress={this.onPressConfirm} style={styles.number} > <Image style={styles.img} source={require("../../assets/Images/SliderImages/Icon/icons_check.png")} /> </TouchableOpacity> ) : ( <TouchableOpacity onPress={() => this.onPressNumber(num.id)} style={styles.number} > <Text style={styles.numberText}>{num.id}</Text> </TouchableOpacity> )} </React.Fragment> ); })} </View> </View> </> ); } } export default PinAuthentication; const styles = StyleSheet.create({ container: { flex: 1, position: "absolute", top: 0, right: 0, left: 0, bottom: 0, backgroundColor: "#021831", }, headerStyle: { flexDirection: "row", marginTop: hRem * 56, marginHorizontal: wRem * 24, alignItems: "center", }, backButton: { width: wRem * 12, height: hRem * 21, }, pinText: { color: "white", textAlign: "center", alignSelf: "center", marginLeft: wRem * 101, fontSize: hRem * 18, ...Theme.encodeSansMed1, lineHeight: hRem * 16, }, pinConfirmationText: { textAlign: "center", marginTop: hRem * 44, color: "white", ...Theme.encodeSansMed3, lineHeight: hRem * 19.07, }, number: { width: wRem * 77, height: hRem * 77, borderRadius: wRem * 77, backgroundColor: "#000000", justifyContent: "center", alignItems: "center", marginHorizontal: wRem * 12, marginVertical: hRem * 9, }, numberContainer: { flexDirection: "row", flexWrap: "wrap", marginTop: hRem * 95, alignItems: "center", justifyContent: "center", shadowColor: Theme.shadow_Button, shadowOffset: { width: 1, height: 1, }, shadowOpacity: 1.5, shadowRadius: 5, elevation: 3, }, numberText: { ...Theme.encodeSansMed4, textAlign: "center", color: Theme.white_color, }, codeContainer: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginHorizontal: wRem * 49, marginTop: hRem * 50, }, // 调整输入位样式,增加高度适配掩码显示 inputBox: { width: wRem * 62, height: hRem * 40, justifyContent: 'center', borderBottomWidth: 1, borderColor: "#FFFFFF", }, inputBox1: { width: wRem * 62, height: hRem * 40, justifyContent: 'center', borderBottomWidth: 1, borderColor: "#00FF00", // 可自定义已填充位的边框颜色做区分 }, // 新增掩码文本样式 maskText: { color: 'white', textAlign: 'center', fontSize: hRem * 20, ...Theme.encodeSansMed3, }, img: { width: wRem * 30, height: hRem * 22, }, // 已删除未使用的冗余样式 });
功能说明
修复后可实现需求的全部效果:
- 点击数字按键自动填充到第一个空输入位,显示
*掩码 - 点击删除按键自动清空最后一个已填充输入位
- 点击确认按键可获取完整4位PIN码,控制台可查看打印结果,可直接扩展业务逻辑
内容的提问来源于stack exchange,提问作者sourabh atigre
相关产品推荐
相关产品推荐

