You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 02:06:03