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

React Native切换密码可见性时输入框内容跳至开头问题求助

React Native切换密码可见性时输入框内容跳至开头的修复方案

问题重现代码

const [password, setPassword] = useState('')
const [passwordVisibility, setPasswordVisibility] = useState(false);

<View style={styles.inputContainer}>
  <TextInput
    name="password"
    style={styles.inputField}
    autoCapitalize='none'
    value={password}
    autoCorrect={false}
    textContentType="newPassword"
    onChangeText={onChangeText}
    placeholder="Password"
    enablesReturnKeyAutomatically
    secureTextEntry={passwordVisibility}
  />
  <Pressable onPress={() => {setPasswordVisibility(!passwordVisibility), console.log(password)}}>
    <Icon name={passwordVisibility == true ? 'eye' : 'eye-off' } size={23} color='purple' />
  </Pressable>
</View>

问题原因

当secureTextEntry属性值变化时,React Native会重新初始化TextInput组件,导致光标位置被强制重置到文本开头。

修复方案

通过保存并恢复光标位置解决该问题,具体实现步骤如下:

  • 给TextInput添加ref引用,用于获取输入框实例
  • 新增状态保存当前光标位置
  • 在切换可见性前记录光标位置,切换后通过ref恢复位置

修改后的完整代码

import { useRef, useState } from 'react';
import { View, TextInput, Pressable } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons'; // 根据实际使用的图标库调整

const PasswordInput = () => {
  const [password, setPassword] = useState('');
  const [passwordVisibility, setPasswordVisibility] = useState(false);
  const [cursorPosition, setCursorPosition] = useState(0);
  const passwordInputRef = useRef(null);

  const togglePasswordVisibility = () => {
    // 切换可见性前,先记录当前光标位置
    if (passwordInputRef.current) {
      const currentSelection = passwordInputRef.current.getSelection();
      setCursorPosition(currentSelection.start);
    }
    // 切换密码可见状态
    setPasswordVisibility(prev => !prev);
  };

  // 恢复光标位置的方法
  const restoreCursor = () => {
    if (passwordInputRef.current) {
      passwordInputRef.current.setSelection(cursorPosition, cursorPosition);
    }
  };

  return (
    <View style={styles.inputContainer}>
      <TextInput
        ref={passwordInputRef}
        name="password"
        style={styles.inputField}
        autoCapitalize='none'
        value={password}
        autoCorrect={false}
        textContentType="newPassword"
        onChangeText={setPassword} // 替换为你原有的onChangeText逻辑
        placeholder="Password"
        enablesReturnKeyAutomatically
        secureTextEntry={passwordVisibility}
        onFocus={restoreCursor}
        onLayout={restoreCursor}
      />
      <Pressable onPress={togglePasswordVisibility}>
        <Icon 
          name={passwordVisibility ? 'eye' : 'eye-off'} 
          size={23} 
          color='purple' 
        />
      </Pressable>
    </View>
  );
};

// 示例样式,可根据项目需求调整
const styles = {
  inputContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 8,
    paddingHorizontal: 12,
    paddingVertical: 8,
  },
  inputField: {
    flex: 1,
    height: 40,
  },
};

export default PasswordInput;

关键说明

  1. passwordInputRef:用来获取TextInput实例,调用getSelection()获取当前光标位置,调用setSelection()恢复光标位置
  2. togglePasswordVisibility:在切换可见性状态前,先捕获当前光标位置并保存到状态中
  3. restoreCursor:在输入框获得焦点或布局更新时,将光标恢复到之前保存的位置
  4. 如果你的onChangeText有自定义处理逻辑,直接替换代码中的setPassword即可

内容的提问来源于stack exchange,提问作者Coder Duck

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:45:38