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 上的双击(句点)的主要内容,如果未能解决你的问题,请参考以下文章
删除行时如何使多行TextInput缩小(React-Native)?
如何使用 react-native 的 TextInput 的 `selectionState` 属性?
React Native 之 TextInput(多个语法知识)
fontFamily 'Arial' 不是使用 react-native-textinput-effects 的系统字体