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

Posted

技术标签:

【中文标题】TextInput 忽略 React Native 上的双击(句点)【英文标题】:TextInput ignores Double Tap (Period) on React Native 【发布时间】:2018-10-18 21:24:23 【问题描述】:

我有 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
        />

【问题讨论】:

注意,启用多行时会产生句点。 【参考方案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
);

您可以根据您的要求对其进行编辑

【讨论】:

我的意思是空格键上的双制表符给你一个句号【参考方案2】:

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 而是使用按钮的多行,我们需要在文本输入中添加一个 ref。

    <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 在视觉上看起来是空的。

【讨论】:

【参考方案3】:

这非常接近苹果的行为。如果有人能找到与苹果功能不相称的方法,请告诉我。

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(/\s2$/, ". ");
            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))
/>

【讨论】:

以上是关于TextInput 忽略 React Native 上的双击(句点)的主要内容,如果未能解决你的问题,请参考以下文章

React Native 组件之TextInput

删除行时如何使多行TextInput缩小(React-Native)?

如何使用 react-native 的 TextInput 的 `selectionState` 属性?

React Native 之 TextInput(多个语法知识)

fontFamily 'Arial' 不是使用 react-native-textinput-effects 的系统字体

TextInput 在 react-native 中隐藏在键盘后面