Android EditText每4位自動添加空格效果

這篇文章主要給大家介紹了關於Android EditText每4位自動添加空格效果的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用EditText具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

基本功能

剛拿到需求,很簡單的一個功能,二話不說,很快就出來了:

完美!順利上線!

沒過幾天領導拿着手機過來說:“這一堆數字在一起看着很費勁,像其他App一樣,加個空格吧!”

於是就有了這個demo。

拓展功能

下面就來在基本功能上做拓展:每4位,自動添加空格。

看似很小的功能,在開發的過程中,遇到了非常多的問題與難點:

  • EditText輸入框監聽死循環
  • 輸入框中的空格無法刪除(刪除又添加)
  • 從中間刪除一個數字產生的一系列問題
  • 輸入框光標位置的控制問題

之前踩坑的過程就不再贅述了,太心酸....

經過一系列的實驗,最後定下來的思路如下:

  • 當輸入框的內容改變時,就將內容取出拆分爲一個一個的字符,在每4位的中間添加空格,最後一個4位不能添加。用這種拼接字符的方法是爲了解決當用戶刪除中間的數字,會導致空格位置錯位的問題。
  • 當用戶刪除中間的字符時,要記錄該動作並且記錄光標位置,保證重新排序完成後,光標的位置在應該在的位置。

大概就這2步,就可以實現這個功能,下面一步一來,我們先實現空格的添加,保證內容永遠滿足4位後一個空格:

下面先看EditText的監聽:

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) {
  //獲取輸入框中的內容,不可以去空格
  String etContent = EditTextUtils.getText(et_credit_number);
  if (TextUtils.isEmpty(etContent)) {
   bt_submit.setEnabled(false);
   return;
  }
  //重新拼接字符串
  String newContent = AppUtils.addSpeaceByCredit(etContent);
  //如果有改變,則重新填充
  //防止EditText無限setText()產生死循環
  if (!etContent.equals(newContent)) {
   et_credit_number.setText(newContent);
   //保證光標在最後,因爲每次setText都會導致光標重置
   //這樣最基本地解決了光標亂跳的問題
   et_credit_number.setSelection(newContent.length());
  }
  //判斷是否滿足信用卡格式,注意去空格判斷
  if (MatcheUtils.isCreditNumber(newContent.replaceAll(" ", ""))) {
   bt_submit.setEnabled(true);
   return;
  }
  bt_submit.setEnabled(false);
 }
});

沒有難點,重新拼接字符串我單獨封裝了出來:

public static String addSpeaceByCredit(String content) {
 if (TextUtils.isEmpty(content)) {
  return "";
 }
 //去空格
 content = content.replaceAll(" ", "");
 if (TextUtils.isEmpty(content)) {
  return "";
 }
 //卡號限制爲16位
 if (content.length() > 16) {
  content = content.substring(0, 16);
 }
 StringBuilder newString = new StringBuilder();
 for (int i = 1; i <= content.length(); i++) {
  //當爲第4位時,並且不是最後一個第4位時
  //拼接字符的同時,拼接一個空格
  //如果在最後一個第四位也拼接,會產生空格無法刪除的問題
  //因爲一刪除,馬上觸發輸入框改變監聽,又重新生成了空格
  if (i % 4 == 0 && i != content.length()) {
   newString.append(content.charAt(i - 1) + " ");
  } else {
  //如果不是4位的倍數,則直接拼接字符即可
   newString.append(content.charAt(i - 1));

  }
 }
 return newString.toString();
}

這裏每一步的含義,我都寫了註釋,應該問題不大,下面運行一下:

完美!空格正常添加了!

但是光標亂跳的問題,我特地演示了一下。

用字符排序的方式來做這個功能的原因是這個,當用戶從中間刪除字符時,我們需要將所有添加的空格位置都進行審查,並重新進行空格的添加,所以我認爲重新排序字符是非常恰當的一種做法。當然這僅僅是我的愚見,可能有更優的做法。

現在我們就要進行第二步,當用戶刪除中間字符時,我們要判斷用戶本次操作是刪除字符,並且保存本次刪除的光標位置,在刪除完成、排序完成之後,將光標移動到保存的光標位置。

思路有了,下面就看最終代碼好了。

功能展示

輸入框監聽的代碼:

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) {
  //因爲重新排序之後setText的存在
  //會導致輸入框的內容從0開始輸入,這裏是爲了避免這種情況產生一系列問題
  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);
  //如果最新的長度 < 上次的長度,代表進行了刪除
  if (editTextContent.length() <= lastString.length()) {
   deleteSelect = start;
  } else {
   deleteSelect = editTextContent.length();
  }
 }
 @Override
 public void afterTextChanged(Editable s) {
  //獲取輸入框中的內容,不可以去空格
  String etContent = EditTextUtils.getText(et_credit_number);
  if (TextUtils.isEmpty(etContent)) {
   bt_submit.setEnabled(false);
   return;
  }
  //重新拼接字符串
  String newContent = AppUtils.addSpeaceByCredit(etContent);
  //保存本次字符串數據
  lastString = newContent;
  //如果有改變,則重新填充
  //防止EditText無限setText()產生死循環
  if (!etContent.equals(newContent)) {
   et_credit_number.setText(newContent);
   //保證光標的位置
   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()的監聽,判斷用戶操作是刪除操作時,保存光標的位置。

小結

項目我已經上傳到了我的GitHub,有興趣的同學可以去參考一下。

這個功能的坑遠遠超出了我的想象,我纔不會說這個項目我就運行了100遍而已!

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對神馬文庫的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章