React Native TextInput 只接受数字字符

React Native TextInput that only accepts numeric characters

我需要一个只允许输入数字字符 (0 - 9) 的 React Native TextInput 组件。我可以将 keyboardType 设置为 numeric 这几乎让我在那里输入除了句点 (.)。但是,这不会阻止将非数字字符粘贴到字段中。

到目前为止我想到的是使用 OnChangeText 事件来查看输入的文本。我从文本中删除了所有非数字字符。然后将文本放在状态字段中。然后通过 Value 属性 更新 TextInput。下面的代码片段。

<TextInput 
  style={styles.textInput}
  keyboardType = 'numeric'
  onChangeText = {(text)=> this.onChanged(text)}
  value = {this.state.myNumber}
/> 

onTextChanged(text) {
  // code to remove non-numeric characters from text
  this.setState({myNumber: text})
}

这似乎行得通,但似乎是个 hack。还有其他方法吗?

在专门开发此类组件(或 TextInput 上的属性)之前,这是正确的做法。

Web 具有输入元素的“数字”类型,但这是基于 Web 的,react-native 不使用 Web 视图。

您可以考虑将该输入创建为它自己的 React 组件(可能调用 NumberInput):这将使您能够重用它甚至开源它,因为您可以创建许多具有不同值的 TextInput filters/checkers.

立即更正的缺点是确保向用户提供正确的反馈,以防止混淆他的值发生了什么

我创建了一个组件来解决这个问题:

https://github.com/amirfl/react-native-num-textinput

你可以这样做。它将只接受数值,并根据您的意愿限制为 10 个数字。

<TextInput 
   style={styles.textInput}
   keyboardType='numeric'
   onChangeText={(text)=> this.onChanged(text)}
   value={this.state.myNumber}
   maxLength={10}  //setting limit of input
/>

您可以在您的页面中写入以下代码来查看输入的值:

{this.state.myNumber}

在 onChanged() 函数中,代码如下所示:

onChanged(text){
    let newText = '';
    let numbers = '0123456789';

    for (var i=0; i < text.length; i++) {
        if(numbers.indexOf(text[i]) > -1 ) {
            newText = newText + text[i];
        }
        else {
            // your call back function
            alert("please enter numbers only");
        }
    }
    this.setState({ myNumber: newText });
}

希望对其他人有所帮助。

<TextInput autoCapitalize={'none'} maxLength={10} placeholder='Mobile Number'  value={this.state.mobile} onChangeText={(mobile) => this.onChanged(mobile)}/>

和 onChanged 方法:

onChanged(text){
   var newText = '';
   var numbers = '0123456789';
   if(text.length < 1){
     this.setState({ mobile: '' });
   }
   for (var i=0; i < text.length; i++) {
        if(numbers.indexOf(text[i]) > -1 ) {
             newText = newText + text[i];
        }
        this.setState({ mobile: newText });
    }
}

使用 RegExp 替换任何非数字比使用带有白名单的 for 循环更快,就像其他答案一样。

将此用于您的 onTextChange 处理程序:

onChanged (text) {
    this.setState({
        mobile: text.replace(/[^0-9]/g, ''),
    });
}

此处进行性能测试:https://jsperf.com/removing-non-digit-characters-from-a-string

使用 RegExp 替换任何非数字。注意下一个代码会给你他找到的第一个数字,所以如果用户粘贴一个包含多个数字 (xx.xx) 的段落,代码会给你第一个数字。如果您想要价格而不是手机,这将有所帮助 phone。

将此用于您的 onTextChange 处理程序:

onChanged (text) {
    this.setState({
        number: text.replace(/[^(((\d)+(\.)\d)|((\d)+))]/g,'_').split("_"))[0],
    });
}

我在 iOS 中遇到了同样的问题,使用 onChangeText 事件来更新用户键入的文本的值我无法更新 TextInput 的值,所以用户仍然会查看他输入的非数字字符。

这是因为,当按下非数字字符时,状态不会改变,因为 this.setState 将使用相同的数字(删除非数字字符后保留的数字),然后 TextInput 将不重新渲染。

我发现解决这个问题的唯一方法是使用 onChangeText 事件之前发生的 keyPress 事件,并在其中使用 setState 将状态值更改为另一个完全不同的值,强制重新渲染onChangeText 事件被调用。对此不是很满意,但它奏效了。

您可以使用正则表达式删除非数字字符

onTextChanged (text) {
    this.setState({
        myNumber: text.replace(/\D/g, ''),
    });
}

这是我的另一个简单答案,使用正则表达式只接受文本框中的数字。

onChanged(text){
    this.setState({ 
         myNumber: text.replace(/[^0-9]/g, '') 
    });
}

对于十进制/浮点数只尝试这个

    onChangeMyFloatNumber(text){
let newText = '';
let numbers = '0123456789.';

for (var i=0; i < text.length; i++) {
    if(numbers.indexOf(text[i]) > -1 ) {
        newText = newText + text[i];
        if(text[i]=="."){
          numbers = '0123456789'
        }
    }
    else {
        // your call back function
        alert("please enter numbers only");
    }
}
this.setState({ MyFloatNumber: newText });

}

验证输入的函数:

validateInputs(text, type) {
let numreg = /^[0-9]+$/;
  if (type == 'username') {
    if (numreg.test(text)) {
      //test ok
    } else {
      //test not ok
    } 
  }
}



<TextInput
   onChangeText={text => this.validateInputs(text, 'username')}
/>

希望对您有所帮助。

我写了这个函数,我发现它有助于防止用户输入我不愿意接受的任何内容。我还使用了 keyboardType="decimal-pad" 和我的 onChangeText={this.decimalTextChange}

  decimalTextChange = (distance) =>
{
    let decimalRegEx = new RegExp(/^\d*\.?\d*$/)
    if (distance.length === 0 || distance === "." || distance[distance.length - 1] === "."
        && decimalRegEx.test(distance)
    ) {
        this.setState({ distance })
    } else {
        const distanceRegEx = new RegExp(/^\s*-?(\d+(\.\d{ 1, 2 })?|\.\d{ 1, 2 })\s*$/)
        if (distanceRegEx.test(distance)) this.setState({ distance })
    }
}

第一个if块是用户删除所有文本或使用小数点作为第一个字符的事件的错误处理,或者如果他们尝试输入多于一位小数,第二个 if 块确保他们可以在小数点前输入任意数量的数字,但在小数点后最多只能输入两位小数。

只允许使用正则表达式的数字

<TextInput 
  keyboardType = 'numeric'
  onChangeText = {(e)=> this.onTextChanged(e)}
  value = {this.state.myNumber}
/> 

onTextChanged(e) {
  if (/^\d+$/.test(e.toString())) { 
    this.setState({ myNumber: e });
  }
}

您可能希望进行不止一次验证


<TextInput 
  keyboardType = 'numeric'
  onChangeText = {(e)=> this.validations(e)}
  value = {this.state.myNumber}
/> 

numbersOnly(e) {
    return /^\d+$/.test(e.toString()) ? true : false
}

notZero(e) {
    return /0/.test(parseInt(e)) ? false : true
}

validations(e) {
    return this.notZero(e) && this.numbersOnly(e)
        ? this.setState({ numColumns: parseInt(e) })
        : false
}

温馨提醒那些遇到 "onChangeText" 无法按预期更改 iOS 上的 TextInput 值的问题:这实际上是 ReactNative 中的一个错误,已在版本 0.57.1​​ 中修复.参考:https://github.com/facebook/react-native/issues/18874

if (!/^[0-9]+$/.test('YourString')) {
  console.log('Enter Only Number');
} else {
    console.log('Success');
}

React Native TextInput 提供具有以下可能值的 keyboardType 道具: 默认 number-pad decimal-pad 数字 email-address phone-pad

因此对于您的情况,您可以使用 keyboardType='number-pad' 来仅接受数字。这不包括“.”

所以,

<TextInput 
  style={styles.textInput}
  keyboardType = 'number-pad'
  onChangeText = {(text)=> this.onChanged(text)}
  value = {this.state.myNumber}
/>

是你必须在你的案例中使用的。

有关详细信息,请参阅 TextInput 的官方文档 link: https://facebook.github.io/react-native/docs/textinput#keyboardtype

第一个解决方案

您可以使用 keyboardType = 'numeric' 作为数字键盘。

  <View style={styles.container}>
        <Text style={styles.textStyle}>Enter Number</Text>
        <TextInput
          placeholder={'Enter number here'}
          style={styles.paragraph}
          keyboardType="numeric"
          onChangeText={value => this.onTextChanged(value)}
          value={this.state.number}
        />
      </View>

在第一种情况下包括标点符号,例如:- .-

第二种解法

使用正则表达式删除标点符号。

 onTextChanged(value) {
    // code to remove non-numeric characters from text
    this.setState({ number: value.replace(/[- #*;,.<>\{\}\[\]\\/]/gi, '') });
  }

请查看零食link

https://snack.expo.dev/@vishaldhanotiya/numeric-keyboard

const [text, setText] = useState('');

const onChangeText = (text) => {
  if (+text) {
    setText(text);
  }
};

<TextInput
  keyboardType="numeric"
  value={text}
  onChangeText={onChangeText}
/>

这应该从物理键盘上省下来

怎么样

onChangeText={(val) => {  
     if(!isNaN(val)){
       //setValue()
     }
  }
keyboardType="numeric"

这将检查数字是否不是数字,然后才会设置文本。

将您的键盘类型更改为数字

<TextInput
onChangeText={this.onChangeText}
 keyboardType={"numeric"}
/>

然后用 space

替换点
onChangeText=(value)=>{
    let text = value.replace(".", '');
              if (isNaN(text)) {
                // Its not a number
                return
              }
    
    console.log("text",text)
    }

我认为,

onChangeText((val:string) => 
    isNaN(Number(val))
       ? val.substr(0, val.length - 1)
       : val
)
// 0     > true
// 0.    > true
// 0.3   > true
// -     > false
// .     > false
// 0.4-  > false
// -1.3  > true

此代码将检查“这不是数字吗?”并且,如果最后一个字符错误,请删除最后一个单词。

如果有人正在寻找允许使用数字键盘而且验证输入只允许一位小数的解决方案,那么下面是我为实现这一目标而写的。我还想将 comma(,) 替换为点 (.),因为这是我将其保存到数据库的方式,但您可以删除它 - 它是可选的。

const [decimalInput, setDecimalInput] = useState('')
const validator = /^[+-]?\d*(?:[.,]\d*)?$/;

function onNumberInputChange(text){
        if (validator.test(text)){
            text = text.replace(",",".") //this is optional
            setDecimalInput(text);
        }
        else{
            //this will remove the last character as it didn't succeed validation
            setDecimalInput(text.substring(0, text.length - 1));
        }
    }

和文本输入组件初始化如下:

<TextInput
                style={{textAlign: 'center'}}
                value = {decimalInput}
                onChangeText={(text) => {
                  setDecimalInput(text);
                  onNumberInputChange(text);
                }}
                placeholder={"type decimal value here..."}
                keyboardType="numeric"
                placeholderTextColor="#ccc">
</TextInput>

也许你们中的一些人需要同样的方法。

如果您使用钩子:

<TextInput
onChangeText={text=> setMyNumber(text?.replace(/[^0-9]/g, ''))}
....
/>

假设文本是使用 useState 钩子初始化的

const [myNumber,setMyNumber]=React.useState('');

如果您添加以下行,那么当您开始输入时,它只会打开数字键盘,而不是字符键盘:

 <TextInput
          placeholder="Enter Mobile No."
          onChangeText={setMobileNumber}
          value={mobileNumber}
          keyboardType="number-pad"
          maxLength={12}
        />