React Native中如何取消TextInput的焦点

67

我正在使用React Native构建一个Android应用。

如何强制TextInput "取消焦点",也就是让光标停止在文本框内闪烁。虽然有isFocused()onFocus()函数,但我该如何让文本框放弃焦点呢?你可能认为一旦我按下回车键,它会自动放弃焦点,但事实并非如此。

   import React, {Component} from 'react';
   import { AppRegistry, Text, View, StyleSheet, TextInput, TouchableOpacity} 
   from 'react-native';

   var SHA256 = require("crypto-js/sha256");

   export default class LoginForm extends Component{


constructor(props){
    super(props);
    this.state = {
        email: '',
        password:''
    };
}

tryLogin = () => {
    if(this.state.email=="email123" && this.state.password == "password"){
        console.log("password verified");
        this.props.navigator.replace({
            title: 'Dashboard'
        });
    }

    console.log(this.state.email);
    console.log(this.state.password);
    console.log("Hash" + SHA256(this.state.password));
}

render(){
    return(
        <View style={styles.container}>
            <TextInput 
                style={styles.input}

                placeholder="Email address" 
                placeholderTextColor="white"
                onChangeText={(email) => this.setState({email})}>
            </TextInput>
            <TextInput style={styles.input} 
                placeholder="Password" 
                placeholderTextColor="white" 
                secureTextEntry
                onChangeText={(password) => this.setState({password})}>
            </TextInput>

            <TouchableOpacity style={styles.loginButtonContainer} onPress={this.tryLogin}>
                <Text style={styles.loginButtonText}>LOGIN</Text>
            </TouchableOpacity>
        </View>
  );
}
}

AppRegistry.registerComponent('LoginForm', () => LoginForm);

const styles =  StyleSheet.create({
container: {
    padding: 20
},
input:{
    height: 40,
    backgroundColor: '#e74c3c',
    marginBottom: 20,
    color: 'white',
    paddingHorizontal: 15,
    opacity: .9
},
loginButtonContainer:{
    justifyContent: 'center',
    backgroundColor: '#bc4c3c',
    paddingVertical:15

},
loginButtonText:{
    textAlign:'center',
    color:'white',
    fontWeight: '700',
    fontSize: 24

}

   })

对于真正的用户来说,这可能并不那么重要,但我只是在模拟,并且如果我想重新加载,这会非常麻烦。


仅使用哈希函数是不够的,仅添加盐也无法有效地提高安全性。相反,应使用带有随机盐的HMAC进行迭代,持续约100毫秒,并将盐与哈希值一起保存。使用诸如PBKDF2Rfc2898DeriveBytespassword_hashBcrypt或类似的函数。关键是要让攻击者花费大量时间通过暴力破解来查找密码。 - zaph
可能是这个问题的重复:在React Native中隐藏键盘 - dǝɥɔS ʇoıןןƎ
11个回答

76

更好的方法是使用 ScrollViewKeyboard.dismiss。当用户点击文本输入框外部时,通过使用 ScrollView 来关闭键盘。这是由于 ScrollView 的默认属性 keyboardShouldPersistTaps 设置为 never。这是用户期望的行为。为了关闭键盘或相当于模糊化 textInput,当用户点击登录按钮时,将Keyboard.dismissed() 添加到 tryLogin 函数中。

import React, {Component} from 'react';
import { AppRegistry, Text, View, StyleSheet, TextInput, TouchableOpacity, ScrollView, Keyboard}
  from 'react-native';
var SHA256 = require("crypto-js/sha256");

export default class LoginForm extends Component{


  constructor(props){
    super(props);
    this.state = {
      email: '',
      password:''
    };
  }

  tryLogin = () => {
    Keyboard.dismiss();
    if(this.state.email=="email123" && this.state.password == "password"){
      console.log("password verified");
      this.props.navigator.replace({
        title: 'Dashboard'
      });
    }

    console.log(this.state.email);
    console.log(this.state.password);
    console.log("Hash" + SHA256(this.state.password));
  }

  render(){
    return(
      <ScrollView style={styles.container}>
        <TextInput
          style={styles.input}

          placeholder="Email address"
          placeholderTextColor="white"
          onChangeText={(email) => this.setState({email})}>
        </TextInput>
        <TextInput style={styles.input}
                   placeholder="Password"
                   placeholderTextColor="white"
                   secureTextEntry
                   onChangeText={(password) => this.setState({password})}>
        </TextInput>

        <TouchableOpacity style={styles.loginButtonContainer} onPress={this.tryLogin}>
          <Text style={styles.loginButtonText}>LOGIN</Text>
        </TouchableOpacity>
      </ScrollView>
    );
  }
}

AppRegistry.registerComponent('LoginForm', () => LoginForm);

const styles =  StyleSheet.create({
  container: {
    padding: 20
  },
  input:{
    height: 40,
    backgroundColor: '#e74c3c',
    marginBottom: 20,
    color: 'white',
    paddingHorizontal: 15,
    opacity: .9
  },
  loginButtonContainer:{
    justifyContent: 'center',
    backgroundColor: '#bc4c3c',
    paddingVertical:15

  },
  loginButtonText:{
    textAlign:'center',
    color:'white',
    fontWeight: '700',
    fontSize: 24

  }

})

1
这个可以运行,如果提交按钮和文本输入框存在于不同的组件中怎么办?在那种情况下你有什么建议? - Vasanth

42

您可以使用键盘API。

import { Keyboard, TextInput } from 'react-native';

<TextInput
  onSubmitEditing={Keyboard.dismiss}
/>
请在React Native官方文档中查看完整示例。

onSubmitEditing 是我一直在寻找的函数。当用户在键盘上按下 nextdone 图标时,该函数将被调用。 - Gabriel Arghire
1
这个多行文本输入框不起作用。 - MD. IBRAHIM KHALIL TANIM
@MD.IBRAHIMKHALILTANIM,如果你设置了blurOnSubmit,它可以用于多行输入。根据文档,默认情况下,对于多行文本输入,它被设置为false - Peter Hägg

15

我使用 this.ref 引用成功解决了这个问题。 首先,你需要为 TextInput 分配一个 ref,像这样:

<input ref="myInput" />

然后,您从一个函数中调用blur()方法来处理this.refs.myInput

 blurTextInput(){
    this.refs.myInput.blur()
 }

1
ref="myInput" 已被弃用。请改用 ref={(ref) => { this.myInput= ref }} 并使用 this.myInput.focus() 或 this.myInput.blur()。 - Prantik Mondal

13

我的使用情况有些不同。用户不会直接在输入框中输入值。该字段主要用于捕获用户尝试输入值并打开模态对话框。我希望在模态对话框关闭后使该字段变模糊,以减少用户稍后需要进行的额外操作。

如果使用 Hooks,您可以执行如下简单操作:

const inputRef = useRef(null);

<Input
  ref={inputRef}
  {...props}
/>

那么您只需在需要的任何地方调用它即可。

inputRef.current.blur();

2
这个回答救了我的一天。谢谢。 - Buwaneka Sudheera
同样的情况发生在我身上。我认为更好的方法是将文本组件设置为不可编辑,并将文本组件包装在视图或可触摸组件中。 - Sacru2red
这个可以运作,但如果textInput在一个组件中,而按钮在另一个组件中怎么办? 通过父级将相同的引用传递给两者并不起作用? 需要帮助吗? - Vasanth
@Vasanth 技术上讲,引用方法应该可以正常工作,除非在调用时引用已过时。您是否检查过模糊处理时引用是否仍然存在? - Keno

8

我找到了它。虽然看起来不是很漂亮,我的直觉告诉我这不是一个非常“react”的解决方案,但如果你想要它,这就是它。

<TextInput 
 style={styles.input} 
 ref="email_input"
 onSubmitEditing={() => this.refs['email_input'].blur()} 
 placeholder="Email address" 
 placeholderTextColor="white"
 onChangeText={(email) => this.setState({email})}/>

2
我在外部点击时使键盘消失,就像这样。
<View onTouchStart={()=>Keyboard.dismiss()} style={{flex: 1, width: "100%"}}>
        <KeyboardAvoidingView style={{flex: 1}}>
                <TextInput></TextInput>
        </KeyboardAvoidingView>
</View>

1

它做了它需要做的事情。

function TextInputCustom({ placeholder, style }) {

    React.useEffect(() => {
        const keyboardHide = Keyboard.addListener('keyboardDidHide', () => {
            Keyboard.dismiss();
        });
        return () => {
            keyboardHide.remove()
        }
    }, []);
    return (
        <TextInput
            style={style}
            placeholder={placeholder}            
        />
    )
}

export default TextInputCustom;

目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

0
我使用了以下代码,它对我来说完美地工作了: 我将所有视图都包裹在TouchableWithoutFeedback中,并且添加了onPress={() => {Keyboard.dismiss();}}。
 import {View,TouchableWithoutFeedback,Keyboard,} from 'react-native';
 ......
<SafeAreaView>
  <ScrollView nestedScrollEnabled={true}>
    <TouchableWithoutFeedback
      onPress={() => {Keyboard.dismiss();}}>
      <View style={styles.container}>
      {/* ..... */}
      </View>
    </TouchableWithoutFeedback>
  </ScrollView>
</SafeAreaView>

0

如果您想在提交后失去焦点,请使用blurOnSubmit属性。

<TextInput 
   blurOnSubmit={true}
   //other props
/>

嗨,Darkleon,欢迎来到SO,请在您的回答中提供更多细节和一个关于如何实现的实际示例。谢谢。 - Abilogos

0

Noah在上面的回答很好,但是在React中使用字符串引用现在已经不鼓励使用了,很可能会很快被弃用。相反,您应该使用一个回调函数,在您想要引用的组件渲染时调用它。

<TextInput 
  ref={(c: any) => {
    this.textInputRef = c;
  }}
  onSubmitEditing={() => this.textInputRef.blur()} 
/>

如果您正在使用Flow,那么您可以在渲染函数之外放置类似于以下内容的代码来指定ref的类型:
textInputRef: ?TextInput;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接