TextInput 在 React Native 上忽略双击(句点)

问题描述 投票:0回答:4

我有 TextInput 组件,每当用户键入时它都会更改状态,但我意识到由于 TextInput 的值使用 this.state.text 作为值,双击空格不会在 iO 上产生句点。

是否有解决办法,以便双击空格仍然可以在 ios 上产生句号?

 onChange =(text) => {
    this.setState({text});
 }




<TextInput
          onChangeText={this.onChange}
          onSubmitEditing={this.onSubmit}
          value={this.state.text}
          autoCapitalize="sentences"
          blurOnSubmit={false}
          editable={true}
        />
reactjs react-native textinput
4个回答
1
投票
import React, { Component } from 'react';
import { AppRegistry, TouchableOpacity, View, TextInput } from 'react-native';

class UselessTextInput extends Component {
    constructor(props) {
        super(props)
        this.state = {
            lastPress: 0
        }
    }

    onPress = () => {
        var delta = new Date().getTime() - this.state.lastPress;

        if (delta < 200) {
            alert("DOUBLE TAP")
            // double tap happend
        }

        this.setState({
            lastPress: new Date().getTime()
        })
    }

    render() {
        return (
            <TouchableOpacity onPress={this.onPress}>
                <TextInput
                    pointerEvents="none"
                />
            </TouchableOpacity>
        );
    }
}

export default class UselessTextInputMultiline extends Component {
    constructor(props) {
        super(props);
        this.state = {
            text: 'Useless Multiline Placeholder',
        };
    }

    // If you type something in the text box that is a color, the background will change to that
    // color.
    render() {
        return (
            <View style={{
                backgroundColor: this.state.text,
                borderBottomColor: '#000000',
                borderBottomWidth: 1
            }}
            >
                <UselessTextInput
                    multiline={true}
                    numberOfLines={4}
                    onChangeText={(text) => this.setState({ text })}
                    value={this.state.text}
                />
            </View>
        );
    }
}

// skip these lines if using Create React Native App
AppRegistry.registerComponent(
    'AwesomeProject',
    () => UselessTextInputMultiline
);

您可以根据您的要求进行编辑,我已经在 React Native 文档网站上尝试过了,并且成功了。


1
投票
textInput 字段上的 onChange 事件会导致问题,例如键盘快捷键(双击空格以创建句点(.)),因为每次击键状态都会改变,并且键盘无法捕获双空格。

因此,我没有将值存储在状态中,而是在提交编辑时捕获它,捕获最终值。

<TextInput onSubmitEditing={this.onSubmit} value={this.state.text} placeholder="Say Something.." blurOnSubmit={false} editable={true} />

然后我们创建一个提交函数,对文本执行某些操作并清除字段。

onSubmit = (e) => { const text = e.nativeEvent.text; this.setState({text}, () => { // <- Important Callback after setstate //Whatever U want to do with the data here. this.setState({text: ''}) // clear the field (this must be in the callback) }) }

我们将 this.state.text 设置为 text,这样我们就可以在之后将其设置回 '' 打回来。如果不执行此步骤,状态不会改变,并且 组件不会刷新空字段。

我意识到通过这种方法,所有键盘功能都将正常工作,包括句点(.)的双倍空格,甚至复制和粘贴值,而无需使用setState。

更新:启用多行的解决方案。

以上适用于单行,对于多行,我们不使用 onSubmitEditing 而是使用按钮,我们需要向文本输入添加引用。

<TextInput ref={input => { this.textMessage = input }} //Important. //onSubmitEditing={this.onSubmit} //Remove so we can use newline value={this.state.text} placeholder="Say Something.." blurOnSubmit={false} editable={true} multiline={true} />

创建一个执行提交的按钮

<Button onPress={this.onSubmit} title="Send" />

有一种不同的方法可以通过 onSubmit 函数的引用来获取值

onSubmit = () => { const text = this.textMessage._lastNativeText.trim(); //Remember the ref from textInput? this.setState({text}, () => { //Do whatever u want with the text here this.setState({text: ''}) //clear the field this.textMessage._lastNativeText = ''; //you need to clear this too })

注意:如果不将 this.textMessage._lastNativeText 设置为空,则 当您单击“发送”时,将继续提交以前的值 按钮,即使 textInput 在视觉上看起来是空的。


1
投票
这与苹果的行为非常接近。如果有人能找到一种与苹果功能不同的方法,请告诉我。

import {useRef} from "react"; const useTextInputReplacer = () => { const lastText = useRef<string>(""); const lastSpaceEnteredAt = useRef<number>(); const periodReplaceDisabled = useRef<boolean>(true); const isLastCharacterAlphaNumeric = str => str[str.length - 1].match(/[a-zA-Z0-9]/); return (_text) => { if (lastText.current && _text.length) { if (lastText.current.length < _text.length) { // add case if (_text[_text.length - 1] === " " && !periodReplaceDisabled.current) { const now = new Date().getTime(); if (lastSpaceEnteredAt.current && (now - lastSpaceEnteredAt.current) < 300) { lastSpaceEnteredAt.current = undefined; _text = _text.replace(/\s{2}$/, ". "); periodReplaceDisabled.current = true; } else if (!periodReplaceDisabled.current && isLastCharacterAlphaNumeric(lastText.current)) { lastSpaceEnteredAt.current = now; } } else { periodReplaceDisabled.current = !isLastCharacterAlphaNumeric(lastText.current); } } else if (lastText.current.length > _text.length) { // deletion case periodReplaceDisabled.current = lastText.current[lastText.current.length - 1] === "." || !isLastCharacterAlphaNumeric(_text); } } lastText.current = _text; return _text; }; };
然后在你的组件中

const textInputReplacer = useTextInputReplacer(); <Input onChangeText={text => updateText(textInputReplacer(text))} />
    

0
投票
我知道已经过去了 6 年,但我看到人们仍在为此苦苦挣扎。这个问题也有一个非常简单的答案,不需要上面发布的所有这些技巧。导致此问题的问题是 value 属性,一旦删除 value 属性,您的本机行为就会恢复。

为什么?因为一旦我们使用了 value,它就变成了一个受控的 TextInput,这意味着每次击键都会触发 onChangeText,并且它会由 React 控制。这可能会破坏本机行为。

只有 onChangeText 和更新状态是不受控制的方式,这是由本机平台控制的,因此允许您双击一段时间 - 也可以提高性能,因为并非所有内容都会在每次击键时重新渲染。除非您确实需要,否则不要使用价值。

© www.soinside.com 2019 - 2024. All rights reserved.