Android之EditText控制禁止输入空格和回车

本文介绍如何通过监听EditText的输入行为来禁止用户输入空格,并保持光标位置不变。同时展示了如何设置EditText使其无法输入回车换行。

前言:

        EdiTtext输入框控制不能输入空格,给EditText添加一个addTextChangedListener监听,如果有空格split截取截取再for循环将截取后不包含空格的字符串数组重新排列这样这个字符串就不包含空格了,最后将这个字符串重新写入EditText,这时会出现一个问题就是光标会自动跳转到第一个位置,在onTextChanged中会有一个叫做start的变量他会传入在这个空格输入之前的光标位置,EditText.setSelection(int)来改变光标的位置具体位置。

一:具体代码:

private EditText edittextcll;// 输入框
edittextcll = (EditText) findViewById(R.id.edittextcll);
//监听输入框禁止输入空格
edittextcll.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before,
                              int count) {

        if (s.toString().contains(" ")) {
            String[] str = s.toString().split(" ");
            String str1 = "";
            for (int i = 0; i < str.length; i++) {
                str1 += str[i];
            }
            edittextcll.setText(str1);

            edittextcll.setSelection(start);

        }

    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
                                  int after) {

    }

    @Override
    public void afterTextChanged(Editable s) {
    }
});

二:.EditText控制不能输入回车,在xml中添加android:singleLine="true"、

<EditText  
 android:id="@+id/edittextcll"  
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 android:layout_marginLeft="5dp"
 android:layout_marginRight="5dp"  
 android:background="@null"  
 android:gravity="top"  
 android:hint="输入更多补充意见" 
 android:singleLine="true" 
 android:textColor="#262626" 
 android:textSize="16dp" />

--------------------大神勿喷,不喜勿喷、

<think>我们需要在Android中限制EditText输入表情特殊字符。可以通过InputFilter来实现,自定义一个过滤器来检查输入的每个字符,如果是不允许的字符(如表情或某些特殊字符),就将其过滤掉。 思路: 1. 创建一个实现InputFilter接口的类。 2. 在filter方法中,检查输入的字符是否在允许的范围内(比如只允许字母、数字、常用标点等)。 3. 我们可以使用正则表达式来匹配表情特殊字符。注意,表情符号通常属于Unicode的Supplementary Planes(补充平面),在Java中这些字符用两个char(代理对)表示。因此,我们需要考虑这种情况。 4. 在过滤器中,我们可以遍历输入的字符序列,检查每个字符(或代理对)是否允许。如果遇到不允许的字符,就过滤掉这个字符(或这个代理对)。 但是,注意:直接过滤掉整个字符序列中的非法字符可能会影响性能,因为每次输入都会调用filter方法。另外,我们也可以考虑使用正则表达式替换非法字符。 然而,由于EditText的InputFilter在每次输入变化时都会调用,所以我们需要一个高效的方法。我们可以使用一个预定义的正则表达式来匹配非法字符(包括表情),然后将其替换为空。 但是,如何定义非法字符?我们可以定义允许的字符集,然后不允许的字符就是不在这个集合中的字符。或者,我们也可以定义不允许的字符集(如表情字符集),然后过滤掉这些字符。 由于表情字符的范围很大,而且不断更新,我们可以选择过滤掉所有非ASCII字符,或者只允许一些基本字符。具体取决于需求。 这里我们假设需求是只允许输入ASCII字符(即0-127的字符),因为表情很多特殊字符都不在ASCII范围内。但是,注意ASCII也包含一些控制字符,我们可能也不想要控制字符(除了换行、回车、制表符等)。 另一种方法是使用Unicode块来过滤表情。但是,Android提供了一个类:Emoji,我们可以使用AndroidX中的Emoji库来判断,但这样会增加依赖。所以,我们这里使用正则表达式来过滤非基本多语言平面(BMP)的字符(即代理对表示的字符,这些通常是表情、象形文字等)以及一些特殊字符。 但是,注意:有些特殊字符可能在BMP中,比如一些货币符号、数学符号等,我们可能也需要过滤。所以,最好根据需求定义允许的字符集。 这里我们采用一个简单的方法:只允许字母(大小写)、数字、空格以及一些常用标点符号。我们可以写一个正则表达式来匹配这些允许的字符,然后过滤掉不在这个集合中的字符。 步骤: 1. 定义允许的正则表达式:例如 [a-zA-Z0-9 ,.!?;:()@#\$%&\*\+\-\/=\[\]\{\}\^_`~<>] 等(根据需求调整)。 2. 在自定义的InputFilter中,使用这个正则表达式来检查每个字符(或每个代码点,因为表情是代码点,可能由两个char组成)。 但是,由于一个代码点可能由两个char(代理对)组成,所以我们需要按代码点来遍历字符序列。 我们可以这样: - 遍历字符序列的每个代码点(使用Character.codePointAt方法) - 对于每个代码点,判断它是否在允许的范围内(即是否匹配我们定义的正则表达式,或者是否小于等于127(ASCII)并且在我们允许的ASCII字符内) 但是,注意:有些ASCII控制字符我们不需要(比如0-31,除了换行、回车等)。所以,我们可以允许的字符包括: - 32-126:这是可打印的ASCII字符(包括空格、标点、字母数字等) - 另外允许一些控制字符:如换行('\n',10)、回车('\r',13)、制表符('\t',9)等。 所以,我们可以这样判断:如果代码点小于等于127,那么检查它是否在我们允许的ASCII字符内(包括控制字符如\n, \r, \t等);如果代码点大于127,那么我们就认为是不允许的(比如表情、汉字等)。或者,如果我们想允许某些非ASCII字符(比如汉字),那么我们就需要调整。 根据问题,我们只讨论限制表情特殊字符。如果需求是只允许ASCII可打印字符一些控制字符,那么我们可以这样: 允许的代码点范围: - 0到31:只允许特定的控制字符(如9,10,13) - 32到126:全部允许 - 大于127:全部不允许 所以,自定义InputFilter如下: 但是,注意:在InputFilter的filter方法中,我们需要返回一个CharSequence,如果返回null则表示接受输入,如果返回一个空字符串则表示删除输入,如果返回一个字符串则表示替换输入。 然而,我们可能需要部分接受输入(比如输入一串字符,其中有一些合法,有一些不合法),那么我们可以构建一个只包含合法字符的字符串返回。 因此,我们可以遍历整个输入字符序列,将合法的字符保留,非法的去掉。 考虑到性能,我们可以在遇到非法字符时才构建新的字符串,否则返回null(表示接受整个输入)。 实现步骤: 1. 遍历输入的字符序列(source),使用代码点遍历。 2. 记录一个合法的字符串,同时记录是否遇到了非法字符。 3. 如果遇到非法字符,我们就开始构建一个新的字符串(只包含合法字符),然后返回这个新字符串。 4. 如果没有遇到非法字符,返回null(表示接受整个输入)。 但是,注意:dest参数表示EditText中已有的文本,我们不需要检查它,我们只需要检查source(即新输入的文本)。但是,如果是在中间插入,那么我们需要检查插入的文本。 另外,InputFilter的filter方法参数说明: - source: 新输入的字符串(如果是单个字符,则是一个长度为1的字符串;如果是粘贴,则可能是一个长字符串) - start: source中要过滤部分的起始索引(一般总是0) - end: source中要过滤部分的结束索引(一般是source的长度) - dest: EditText中已有的文本 - dstart: 新内容要插入的位置(在dest中的起始索引) - dend: 新内容要替换dest中dstart到dend位置的内容(一般如果我们是在中间插入,dend等于dstart,表示不替换原有字符,只是插入) 因此,我们只需要过滤source中从start到end的部分。 代码实现: 我们创建一个InputFilter,然后将其设置EditText。 示例代码: 自定义InputFilter:</think>在 Android 中限制 `EditText` 输入表情特殊字符,可以通过自定义 `InputFilter` 实现。以下是完整解决方案: ### 解决方案代码 ```kotlin import android.text.InputFilter import android.text.Spanned class EmojiSpecialCharFilter : InputFilter { override fun filter( source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int ): CharSequence? { // 遍历输入的每个字符 for (i in start until end) { val codePoint = Character.codePointAt(source, i) val type = Character.getType(codePoint) // 检测条件:1. 表情符号 2. 特殊字符 if (isEmoji(type) || isInvalidSymbol(codePoint)) { return "" // 拒绝非法输入 } } return null // 接受合法输入 } // 判断是否为表情符号(Unicode 类型) private fun isEmoji(type: Int): Boolean { return type == Character.SURROGATE.toInt() || type == Character.OTHER_SYMBOL.toInt() || type == Character.NON_SPACING_MARK.toInt() } // 判断是否为特殊字符(按需扩展) private fun isInvalidSymbol(codePoint: Int): Boolean { // 示例:过滤 ASCII 控制字符(0-31)扩展字符(127-159) return (codePoint in 0..31) || (codePoint in 127..159) } } ``` ### 使用方式 在 Activity/Fragment 中设置过滤器: ```kotlin val editText = findViewById<EditText>(R.id.editText) editText.filters = arrayOf(EmojiSpecialCharFilter()) ``` ### 关键代码解释 1. **`filter()` 方法**: - 系统在每次输入变化时自动调用 - `source`:新输入的字符序列 - 返回 `""` 表示拒绝输入,返回 `null` 表示接受输入 2. **表情检测原理**: - `Character.getType()` 获取 Unicode 字符类型 - 关键类型标识: - `SURROGATE`:代理对(表情组成部分) - `OTHER_SYMBOL`:图形符号(含表情) - `NON_SPACING_MARK`:组合字符(如肤色修饰符) 3. **特殊字符过滤**: - 示例过滤 ASCII 控制字符(0-31)扩展控制字符(127-159) - 可根据需求扩展 `isInvalidSymbol()` 中的逻辑 ### 高级优化建议 1. **正则表达式增强**(如需复杂规则): ```kotlin private val invalidPattern = Regex("[\uD800-\uDBFF]|[\uDC00-\uDFFF]|[\u2600-\u27BF]") private fun isInvalidChar(c: Char): Boolean { return invalidPattern.containsMatchIn(c.toString()) } ``` 2. **错误提示**: ```kotlin editText.setOnKeyListener { _, _, event -> if (event.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER) { Toast.makeText(context, "不支持输入特殊字符", Toast.LENGTH_SHORT).show() } false } ``` 3. **XML 属性支持**(自定义 View): ```kotlin class FilteredEditText : AppCompatEditText { // 添加可在XML中配置的过滤属性 } ``` ### 注意事项 - **代理对处理**:表情符号由 2 个 char(代理对)组成,需用 `Character.codePointAt()` 完整解析 - **性能优化**:避免在 `filter()` 中执行耗时操作 - **输入法兼容**:某些输入法可能预组合字符,实际测试需覆盖多设备
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶已初秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值