草庐IT

Android 输入框(EditText)的输入限制,数字英文邮箱,可见\隐藏切换,踩过的坑!

&岁月不待人& 2023-09-20 原文

目录

一、输入框的输入限制

1.在xml文件里通过设置属性限制输入

2.在代码里动态设置输入限制

二、密码可见性切换和遇到的坑


最近做到了登录注册模块的各种输入判定,监听等等,因为需求上的需要,还是搞了好一会儿,今天在这总结一下。

常规的输入框输入需求有纯数字,字母,混合输入,邮箱,键盘默认打开数字键盘,密码可见性,键盘的收起弹出等等。

一、输入框的输入限制

1.在xml文件里通过设置属性限制输入

1.inputType

例如:输入纯数字,则只需要在editText控件属性下加一句:android:inputType="number"  

常用的属性有:

android:inputType="none"输入普通字符

android:inputType="text"      输入普通字符

android:inputType="textCapCharacters"     输入普通字符

android:inputType="textCapWords"      单词首字母大小

android:inputType="textCapSentences"      仅第一个字母大小

android:inputType="textAutoCorrect"         前两个自动完成

android:inputType="textAutoComplete"    前两个自动完成

android:inputType="textMultiLine"      多行输入

android:inputType="textImeMultiLine"       输入法多行(不一定支持)

android:inputType="textNoSuggestions"   不提示

android:inputType="textUri"      URI格式

android:inputType="textEmailAddress"    电子邮件地址格式

android:inputType="textEmailSubject"    邮件主题格式

android:inputType="textShortMessage"    短消息格式

android:inputType="textLongMessage"     长消息格式

android:inputType="textPersonName"      人名格式

android:inputType="textPostalAddress"   邮政格式

android:inputType="textPassword"      密码格式

android:inputType="textVisiblePassword"     密码可见格式

android:inputType="textWebEditText"作为网页表单的文本格式

android:inputType="textFilter"              文本筛选格式

android:inputType="textPhonetic"        拼音输入格式

android:inputType="number"      数字格式

android:inputType="numberSigned"     有符号数字格式

android:inputType="numberDecimal"   可以带小数点的浮点格式

android:inputType="phone"      拨号键盘

android:inputType="datetime"  日期+时间格式

android:inputType="date"      日期键盘

android:inputType="time"      时间键盘

这个属性,配置后键盘会有不同的展现方式,根据手机的键盘软件自适应,有些属性会限制输入,有些则不会,例如number会限制你只能输入数字,textPassword会把输入的内容占位但不可见,就和输入QQ密码一样。

2.在xml里面设置digits属性

android:digits="!@#$qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"

那么他就只能输入以上digits里面的内容.

2.在代码里动态设置输入限制

1.通过setKeyListener进行限制(kotlin)

editText.keyListener = DigitsKeyListener.getInstance("qwertyuiopasdfghjklzx"+
"cvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890\\_~@#$^")

eg1:为啥会有两个\\呢,因为\是转义字符,所以第一个是拿来转义后面的\的。不了解转义字符的可以看下面链接:

什么是转义字符?转义字符有哪些?为什么使用转义字符?_程序猿!=程序员的博客-CSDN博客_转义字符接上文转义字符相关内容学习。https://blog.csdn.net/AGood_Coder/article/details/125646709?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616366216782388082809%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616366216782388082809&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-125646709-null-null.142%5Ev59%5Epc_rank_34_2,201%5Ev3%5Econtrol_1&utm_term=%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6&spm=1018.2226.3001.41872.判断邮箱格式

  fun checkEditInput(string: String?): Boolean {
        val pattern = Pattern.compile("[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}")
        return ((string?.length ?: 0) > 0) && pattern.matcher(string ?: "").matches()
    }

这个是写的正则表达式,用来判断邮箱格式的,返回的布尔值代表格式是否正确

3.通过InputFilter来过滤输入

 val typeFilter = InputFilter { source, _, _, _, _, _ ->
// p: Pattern = Pattern.compile("[0-9a-zA-Z|\u4e00-\u9fa5]+")  //限制输入中英文,数字
 val p: Pattern = Pattern.compile("[0-9a-zA-Z|!@#$]+")//限制输入数字英文和部分特殊字符
 val m: Matcher = p.matcher(source.toString())
 if (!m.matches()) "" else null
 }
 searchEdit?.filters = arrayOf(typeFilter, InputFilter.LengthFilter(10))

 eg:上面的代码是kotlin哈,他其实是复写了里面的filter方法,这里我把java代码也粘出来。

 InputFilter typeFilter = new InputFilter() {
     @Override
     public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
     Pattern p = Pattern.compile("[0-9a-zA-Z|\u4e00-\u9fa5]+");
     Matcher m = p.matcher(source.toString());
     if (!m.matches()) return "";
     return null;
     }
   };

    //如果要限制输入字数,数组中加上new InputFilter.LengthFilter(maxLength)
    searchEdit.setFilters(new InputFilter[]{typeFilter, new         InputFilter.LengthFilter(10)});

解析:setFilters() 方法,传入的参数是一个filter列表,在上面代码中,为啥我后面又补了一个InputFilter.LengthFilter(10)呢,因为如果不加上这个,会让xml布局里面的maxLength属性失效,因为在TextVIew的源码的构造方法中有一个变量maxLength它对应xml中属性android:maxLength,如果有值就赋值给变量maxLength,如果大于等于0,就调用setFilters(),传入一个InputFilter.LengthFilter。但是我们又在自己的代码中又setFilters了,就把以前的属性替换掉了,所以,要在这儿补上去哦!

TextView源码:

public TextView(
            Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        ...
        int maxlength = -1;
        ...
        case com.android.internal.R.styleable.TextView_maxLength:
                    maxlength = a.getInt(attr, -1);
                    break;
        ...
        if (maxlength >= 0) {
            setFilters(new InputFilter[] { new InputFilter.LengthFilter(maxlength) });
        } else {
            setFilters(NO_FILTERS);
        }
        ...
}

关于Patter和Matcher的用法:我爱学Java之Pattern和Matcher用法_Java.Sheng的博客-CSDN博客Java正则表达式通过java.util.regex包下的Pattern和Matcher类实现Pattern类用于创建一个正则表达式,也可以说是创建一个匹配模式,可以通过两个静态方法创建:compile(String regex)和compile(String regex,int flags),其中regex是正则表达式,flags为可选模式(如:Pattern.CASE_INSENSITIVE 忽https://blog.csdn.net/woaigaolaoshi/article/details/50970527?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166616851916782390521627%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166616851916782390521627&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-50970527-null-null.142%5Ev59%5Epc_rank_34_2,201%5Ev3%5Econtrol_1&utm_term=Matcher&spm=1018.2226.3001.4187

4.代码里通过设置InputType

这个就和xml里属性设置差不多,不过代码里更加灵活。下面的代码就是动态设置输入内容可见/不可见,就是类似于QQ密码的那个眼睛图标的功能。

    private fun setEditPassword(editText: EditText, passwordVisible: Boolean) {
        if (passwordVisible) { //选择状态 显示明文--设置为可见的密码
            editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
        } else { //默认状态显示密码--设置文本 要一起写才能起作用  InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
            editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
        }
    }

 以上就是输入限制的一些方法,可以根据需求打一套组合拳,但是有些方法也会有冲突导致失效,这时候就可以去看看源码。

二、密码可见性切换和遇到的坑

1.使用setKeyListner和inputType组合使用的冲突:

需求:1.对密码输入做限制2.密码可点击眼睛图标进行可见、隐藏。

限制代码

editText.keyListener = DigitsKeyListener.getInstance("qwertyuiopasdfghjklzx"+
"cvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890\\_~@#$^")

点击事件进行密码隐藏

    private fun setEditPassword(editText: EditText, passwordVisible: Boolean) {
        if (passwordVisible) { //选择状态 显示明文--设置为可见的密码
            editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
        } else { //默认状态显示密码--设置文本 要一起写才能起作用  InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
            editText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
        }
    }

冲突表现:点击图标进行切换后,原来的keyListener设置的限制失效,可以输入任意字符

原因看源码:在keyListener里,

public void setKeyListener(KeyListener input) {
        mListenerChanged = true;
        setKeyListenerOnly(input);
        fixFocusableAndClickableSettings();

        if (input != null) {
            createEditorIfNeeded();
            setInputTypeFromEditor();
        } else {
            if (mEditor != null) mEditor.mInputType = EditorInfo.TYPE_NULL;
        }

        InputMethodManager imm = getInputMethodManager();
        if (imm != null) imm.restartInput(this);
    }

看最后两行,这儿会将软键盘重置了,故使用的软键盘是其自己getInputType方法得到的数字键盘模式。

他的getInputType方法源码:

/**
     * Returns the input type for the listener.
     */
    public int getInputType() {
        int contentType;
        if (mNeedsAdvancedInput) {
            contentType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
        } else {
            contentType = InputType.TYPE_CLASS_NUMBER;
            if (mSign) {
                contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
            }
            if (mDecimal) {
                contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
            }
        }
        return contentType;
    }

接下来:

    public void setInputType(int type) {
        final boolean wasPassword = isPasswordInputType(getInputType());
       ......有点多我删了,看下面

        InputMethodManager imm = getInputMethodManager();
        if (imm != null) imm.restartInput(this);
    }

看最后两行,这儿setInputType方法将软键盘重置成全键盘模式,前面设置的DigitsKeyListener就失效了,变成新的。

解决办法1:在setEditPassword这个方法设置密码可见\隐藏后,再设置限制,这样就不会失效了,相当于每次点击图标切换,都会对输入框进行一次设定,相比于输入框的一些监听事件啊,这种操作也可以接受。(这个方法可能会因为inputType变化频繁导致部分手机的键盘切两次哦,所以这个方法不大完美!)

解决方法2:新的组合拳!!!InputFilter+setInputType

代码:将上面的setKeyListener干掉,用下面的方法限制,就完美结局了,有maxLength记得补上哦~

val typeFilter = InputFilter { source, start, end, dest, dstart, dend -> //限制只能输入中文,英文,数字
            //            val p: Pattern = Pattern.compile("[0-9a-zA-Z|\u4e00-\u9fa5]+")
            val p: Pattern = Pattern.compile("[0-9a-zA-Z|!@#$]+")
            val m: Matcher = p.matcher(source.toString())
            if (!m.matches()) "" else null
        }
       editText?.filters = arrayOf(typeFilter, InputFilter.LengthFilter(10))
       

 这块的总结就到这儿了,有疑问的欢迎评论区讨论哈,有不对的地方望大佬指教!

有关Android 输入框(EditText)的输入限制,数字英文邮箱,可见\隐藏切换,踩过的坑!的更多相关文章

  1. ruby-on-rails - Ruby on Rails with Haml - 如何从 erb 切换 - 2

    我正在从erb文件切换到HAML。我将hamlgem添加到我的系统中。我创建了app/views/layouts/application.html.haml文件。我应该只删除application.html.erb文件吗?此外,仍然有/public/index.html文件被呈现为默认页面。我想创建自己的默认index.html.haml页面。我应该把它放在哪里以及如何使系统呈现该文件而不是默认索引文件?谢谢! 最佳答案 是的,您可以删除任何已转换为HAML的View的ERB版本。至于你的另一个问题,删除public/index/h

  2. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  3. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  4. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  5. ruby - 正则表达式将非英文字母匹配为非单词字符 - 2

    @raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://

  6. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  7. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  8. ruby - 将n维数组的每个元素乘以Ruby中的数字 - 2

    在Ruby中,是否有一种简单的方法可以将n维数组中的每个元素乘以一个数字?这样:[1,2,3,4,5].multiplied_by2==[2,4,6,8,10]和[[1,2,3],[1,2,3]].multiplied_by2==[[2,4,6],[2,4,6]]?(很明显,我编写了multiplied_by函数以区别于*,它似乎连接了数组的多个副本,不幸的是这不是我需要的)。谢谢! 最佳答案 它的长格式等价物是:[1,2,3,4,5].collect{|n|n*2}其实并没有那么复杂。你总是可以使你的multiply_by方法:c

  9. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  10. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

随机推荐