Android EditText每4位自動(dòng)添加空格效果
基本功能
剛拿到需求,很簡(jiǎn)單的一個(gè)功能,二話不說(shuō),很快就出來(lái)了:
完美!順利上線!
沒(méi)過(guò)幾天領(lǐng)導(dǎo)拿著手機(jī)過(guò)來(lái)說(shuō):“這一堆數(shù)字在一起看著很費(fèi)勁,像其他App一樣,加個(gè)空格吧!”
于是就有了這個(gè)demo。
拓展功能
下面就來(lái)在基本功能上做拓展:每4位,自動(dòng)添加空格。
看似很小的功能,在開(kāi)發(fā)的過(guò)程中,遇到了非常多的問(wèn)題與難點(diǎn):
- EditText輸入框監(jiān)聽(tīng)死循環(huán)
- 輸入框中的空格無(wú)法刪除(刪除又添加)
- 從中間刪除一個(gè)數(shù)字產(chǎn)生的一系列問(wèn)題
- 輸入框光標(biāo)位置的控制問(wèn)題
之前踩坑的過(guò)程就不再贅述了,太心酸....
經(jīng)過(guò)一系列的實(shí)驗(yàn),最后定下來(lái)的思路如下:
- 當(dāng)輸入框的內(nèi)容改變時(shí),就將內(nèi)容取出拆分為一個(gè)一個(gè)的字符,在每4位的中間添加空格,最后一個(gè)4位不能添加。用這種拼接字符的方法是為了解決當(dāng)用戶刪除中間的數(shù)字,會(huì)導(dǎo)致空格位置錯(cuò)位的問(wèn)題。
- 當(dāng)用戶刪除中間的字符時(shí),要記錄該動(dòng)作并且記錄光標(biāo)位置,保證重新排序完成后,光標(biāo)的位置在應(yīng)該在的位置。
大概就這2步,就可以實(shí)現(xiàn)這個(gè)功能,下面一步一來(lái),我們先實(shí)現(xiàn)空格的添加,保證內(nèi)容永遠(yuǎn)滿足4位后一個(gè)空格:
下面先看EditText的監(jiān)聽(tīng):
et_credit_number.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { //獲取輸入框中的內(nèi)容,不可以去空格 String etContent = EditTextUtils.getText(et_credit_number); if (TextUtils.isEmpty(etContent)) { bt_submit.setEnabled(false); return; } //重新拼接字符串 String newContent = AppUtils.addSpeaceByCredit(etContent); //如果有改變,則重新填充 //防止EditText無(wú)限setText()產(chǎn)生死循環(huán) if (!etContent.equals(newContent)) { et_credit_number.setText(newContent); //保證光標(biāo)在最后,因?yàn)槊看蝧etText都會(huì)導(dǎo)致光標(biāo)重置 //這樣最基本地解決了光標(biāo)亂跳的問(wèn)題 et_credit_number.setSelection(newContent.length()); } //判斷是否滿足信用卡格式,注意去空格判斷 if (MatcheUtils.isCreditNumber(newContent.replaceAll(" ", ""))) { bt_submit.setEnabled(true); return; } bt_submit.setEnabled(false); } });
沒(méi)有難點(diǎn),重新拼接字符串我單獨(dú)封裝了出來(lái):
public static String addSpeaceByCredit(String content) { if (TextUtils.isEmpty(content)) { return ""; } //去空格 content = content.replaceAll(" ", ""); if (TextUtils.isEmpty(content)) { return ""; } //卡號(hào)限制為16位 if (content.length() > 16) { content = content.substring(0, 16); } StringBuilder newString = new StringBuilder(); for (int i = 1; i <= content.length(); i++) { //當(dāng)為第4位時(shí),并且不是最后一個(gè)第4位時(shí) //拼接字符的同時(shí),拼接一個(gè)空格 //如果在最后一個(gè)第四位也拼接,會(huì)產(chǎn)生空格無(wú)法刪除的問(wèn)題 //因?yàn)橐粍h除,馬上觸發(fā)輸入框改變監(jiān)聽(tīng),又重新生成了空格 if (i % 4 == 0 && i != content.length()) { newString.append(content.charAt(i - 1) + " "); } else { //如果不是4位的倍數(shù),則直接拼接字符即可 newString.append(content.charAt(i - 1)); } } return newString.toString(); }
這里每一步的含義,我都寫(xiě)了注釋,應(yīng)該問(wèn)題不大,下面運(yùn)行一下:
完美!空格正常添加了!
但是光標(biāo)亂跳的問(wèn)題,我特地演示了一下。
用字符排序的方式來(lái)做這個(gè)功能的原因是這個(gè),當(dāng)用戶從中間刪除字符時(shí),我們需要將所有添加的空格位置都進(jìn)行審查,并重新進(jìn)行空格的添加,所以我認(rèn)為重新排序字符是非常恰當(dāng)?shù)囊环N做法。當(dāng)然這僅僅是我的愚見(jiàn),可能有更優(yōu)的做法。
現(xiàn)在我們就要進(jìn)行第二步,當(dāng)用戶刪除中間字符時(shí),我們要判斷用戶本次操作是刪除字符,并且保存本次刪除的光標(biāo)位置,在刪除完成、排序完成之后,將光標(biāo)移動(dòng)到保存的光標(biāo)位置。
思路有了,下面就看最終代碼好了。
功能展示
輸入框監(jiān)聽(tīng)的代碼:
et_credit_number.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //因?yàn)橹匦屡判蛑髎etText的存在 //會(huì)導(dǎo)致輸入框的內(nèi)容從0開(kāi)始輸入,這里是為了避免這種情況產(chǎn)生一系列問(wèn)題 if (start == 0 && count > 0) { return; } String editTextContent = EditTextUtils.getText(et_credit_number); if (TextUtils.isEmpty(editTextContent) || TextUtils.isEmpty(lastString)) { return; } editTextContent = AppUtils.addSpeaceByCredit(editTextContent); //如果最新的長(zhǎng)度 < 上次的長(zhǎng)度,代表進(jìn)行了刪除 if (editTextContent.length() <= lastString.length()) { deleteSelect = start; } else { deleteSelect = editTextContent.length(); } } @Override public void afterTextChanged(Editable s) { //獲取輸入框中的內(nèi)容,不可以去空格 String etContent = EditTextUtils.getText(et_credit_number); if (TextUtils.isEmpty(etContent)) { bt_submit.setEnabled(false); return; } //重新拼接字符串 String newContent = AppUtils.addSpeaceByCredit(etContent); //保存本次字符串?dāng)?shù)據(jù) lastString = newContent; //如果有改變,則重新填充 //防止EditText無(wú)限setText()產(chǎn)生死循環(huán) if (!etContent.equals(newContent)) { et_credit_number.setText(newContent); //保證光標(biāo)的位置 et_credit_number.setSelection(deleteSelect > newContent.length() ? newContent.length() : deleteSelect); } //判斷是否滿足信用卡格式,注意去空格判斷 if (MatcheUtils.isCreditNumber(newContent.replaceAll(" ", ""))) { bt_submit.setEnabled(true); return; } bt_submit.setEnabled(false); } });
這邊主要利用了onTextChanged()的監(jiān)聽(tīng),判斷用戶操作是刪除操作時(shí),保存光標(biāo)的位置。
小結(jié)
項(xiàng)目我已經(jīng)上傳到了我的GitHub,有興趣的同學(xué)可以去參考一下。
這個(gè)功能的坑遠(yuǎn)遠(yuǎn)超出了我的想象,我才不會(huì)說(shuō)這個(gè)項(xiàng)目我就運(yùn)行了100遍而已!
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Android用tabhost實(shí)現(xiàn) 界面切換,每個(gè)界面為一個(gè)獨(dú)立的activity操作
這篇文章主要介紹了Android用tabhost實(shí)現(xiàn) 界面切換,每個(gè)界面為一個(gè)獨(dú)立的activity操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-049個(gè)非常棒的Android代碼編輯器 移動(dòng)開(kāi)發(fā)者的最愛(ài)
這篇文章主要為大家分享了9個(gè)非常棒的Android代碼編輯器,據(jù)說(shuō)這可是移動(dòng)開(kāi)發(fā)者的最愛(ài),知道是哪九個(gè)Android代碼編輯器2015-12-12Android 下載網(wǎng)絡(luò)圖片并顯示到本地
本文主要介紹了Android實(shí)現(xiàn)下載網(wǎng)絡(luò)圖片并顯示到本地功能的示例代碼。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-03-03在Android設(shè)備上搭建Web服務(wù)器的方法
本篇文章主要介紹了在Android設(shè)備上搭建Web服務(wù)器的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Android列表實(shí)現(xiàn)(1)_數(shù)組列表實(shí)例介紹
最近開(kāi)始學(xué)習(xí)android的ui,先上幾個(gè)相關(guān)的例子,后續(xù)還會(huì)有更新,感興趣的朋友可以研究下2012-12-12Android中使用include標(biāo)簽和merge標(biāo)簽重復(fù)使用布局
這篇文章主要介紹了Android中使用include標(biāo)簽和merge標(biāo)簽重復(fù)使用布局,文中講解了創(chuàng)建可復(fù)用布局的例子以及include標(biāo)簽和merge標(biāo)簽使用例子,需要的朋友可以參考下2014-06-06Android自定義View實(shí)現(xiàn)繪制水波浪溫度刻度表
這篇文章主要為大家詳細(xì)介紹了Android如何利用自定義View實(shí)現(xiàn)一個(gè)水波浪溫度刻度表,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-11-11