Automatically add dash in phone number in Android - android

Instead of 5118710, it should be 511-8710. I'd like to add a dash after the user the user inputted 3 digits already in the EditText. The maximum length of the EditText is 7 digits only.
After I figured out the above problem, I've got stuck in coding again. When I already inputted 3 digits, it appends dash (that's what I'd like to happen) but my problem here is that the next 3 digits also appends dash (Like this: 511-871-)... Please help me with this. thanks!
txt_HomeNo.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean flag = true;
String eachBlock[] = txt_HomeNo.getText().toString().split("-");
for (int i = 0; i < eachBlock.length; i++) {
if (eachBlock[i].length() > 3) {
flag = false;
}
}
if (flag) {
txt_HomeNo.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL)
keyDel = 1;
return false;
}
});
if (keyDel == 0) {
if (((txt_HomeNo.getText().length() + 1) % 4) == 0) {
if (txt_HomeNo.getText().toString().split("-").length <= 3) {
txt_HomeNo.setText(txt_HomeNo.getText() + "-");
txt_HomeNo.setSelection(txt_HomeNo.getText().length());
}
}
a = txt_HomeNo.getText().toString();
} else {
a = txt_HomeNo.getText().toString();
keyDel = 0;
}
} else {
txt_HomeNo.setText(a);
}
}

The most straightforward solution is to use PhoneNumberFormattingTextWatcher which will format the number according to the system locale.
XML:
<EditText
android:id="#+id/phone_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/enter_phone_number"
android:inputType="phone" />
Add addTextChangedListener() in your class:
EditText phoneNumber = (EditText)findViewById(R.id.phone_number);
phoneNumber.addTextChangedListener(new PhoneNumberFormattingTextWatcher());

Implement the following modified addTextChangedListener for txt_HomeNo. The code below is checking if the length of the text entered is 3 and if it is then add the - to it. Not a very robust solution but it works!
txt_HomeNo.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
txt_HomeNo.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL)
keyDel = 1;
return false;
}
});
if (keyDel == 0) {
int len = txt_HomeNo.getText().length();
if(len == 3) {
txt_HomeNo.setText(txt_HomeNo.getText() + "-");
txt_HomeNo.setSelection(txt_HomeNo.getText().length());
}
} else {
keyDel = 0;
}
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
});

I have a few small changes to the solution of neo108 so it can work with both soft keyboard and hard keyboard, in my code for example the edittext will follow the rule to automatically add " " at position 5 and 9.
txtPhone.addTextChangedListener(new TextWatcher() {
int keyDel;
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
txtPhone.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
keyDel = 1;
}
return false;
}
});
String currentString = txtPhone.getText().toString();
int currentLength = txtPhone.getText().length();
if (currentLength == 5 || currentLength == 9) {
keyDel = 1;
}
if (keyDel == 0) {
if (currentLength == 4 || currentLength == 8) {
txtPhone.setText(txtPhone.getText() + " ");
txtPhone.setSelection(txtPhone.getText().length());
}
} else {
if (currentLength != 5 && currentLength != 9) {
keyDel = 0;
} else if ((currentLength == 5 || currentLength == 9)
&& !" ".equals(currentString.substring(currentLength - 1, currentLength))) {
txtPhone.setText(currentString.substring(0, currentLength - 1) + " "
+ currentString.substring(currentLength - 1, currentLength));
txtPhone.setSelection(txtPhone.getText().length());
}
}
}

I implemented a custom TextWatcher; this handles 10 and 11 digit phone numbers (i.e. 1-555-867-5309 and 555-867-5309). Allows adds, deletions, inserts, mass removal while maintaining proper cursor position.
public class CustomPhoneTextWatcher implements TextWatcher {
private final EditText editText;
private String previousString;
public CustomPhoneTextWatcher(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
// if the previous editable ends with a dash and new is shorter than previous
// additionally remove preceding character
if (previousString != null && previousString.endsWith("-") && editable.toString().length() < previousString.length()) {
previousString = editable.toString();
String removedCharacterPriorToDash = editable.toString().substring(0, editable.length() - 1);
editText.setText(removedCharacterPriorToDash);
int position = editText.length();
Editable etext = editText.getText();
Selection.setSelection(etext, position);
} else {
previousString = editable.toString();
String numericString = StringUtils.removeNonnumeric(editable.toString());
int stringLength = numericString.length();
boolean startsWithOne = numericString.startsWith("1");
numericString = numericString.substring(0, Math.min(stringLength, 10 + (startsWithOne ? 1 : 0)));
int lastHyphenIndex = 6 + (startsWithOne ? 1 : 0);
int secondToLastHyphenIndex = 3 + (startsWithOne ? 1 : 0);
if (stringLength >= lastHyphenIndex) {
numericString = numericString.substring(0, lastHyphenIndex) + "-" + numericString.substring(lastHyphenIndex, numericString.length());
}
if (stringLength >= secondToLastHyphenIndex) {
numericString = numericString.substring(0, secondToLastHyphenIndex) + "-" + numericString.substring(secondToLastHyphenIndex, numericString.length());
}
if (numericString.startsWith("1")) {
numericString = numericString.substring(0, 1) + "-" + numericString.substring(1, numericString.length());
}
if (!numericString.equals(editable.toString())) {
editText.setText(numericString);
int position = editText.length();
Editable etext = editText.getText();
Selection.setSelection(etext, position);
}
}
}
}
StringUtils.removeNonnumeric(editable.toString()) is a call to this method:
public static String removeNonnumeric(String text) {
return text.replaceAll("[^\\d]", "");
}

Thanks for the all above answer.
The editText.setOnKeyListener() will never invoke when your device has only soft keyboard.
If we strictly follow the rule to add "-", then this code not always show desire result.
editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher());
but above code is best solution for formatting phone no.
Apart from above this solution, I write a code which work on all types of condition::
phoneNumber.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) {
if (len > phoneNumber.getText().length() ){
len--;
return;
}
len = phoneNumber.getText().length();
if (len == 4 || len== 8) {
String number = phoneNumber.getText().toString();
String dash = number.charAt(number.length() - 1) == '-' ? "" : "-";
number = number.substring(0, (len - 1)) + dash + number.substring((len - 1), number.length());
phoneNumber.setText(number);
phoneNumber.setSelection(number.length());
}
}
});
this line of code required to add "-" on 3rd & 6th position of number.
if (len == 4 || len== 8)

Do it yourself by using OnEditTextChangedListener and insert dash by counting number of chars, Counting Chars in EditText Changed Listener

import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
/**
* Auto-formats a number using -.
* Ex. 303-333-3333
* Ex. 1-303-333-3333
* Doesn't allow deletion of just -
*/
public class PhoneNumberFormattingTextWatcher implements TextWatcher {
private static final String TAG = "PhoneNumberTextWatcher";
private final EditText editText;
private String previousNumber;
/**
* Indicates the change was caused by ourselves.
*/
private boolean mSelfChange = false;
public PhoneNumberFormattingTextWatcher(EditText editText) {
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
// if the previous editable ends with a dash and new is shorter than previous
// additionally remove preceding character
Log.i(TAG, "Previous String: " + previousNumber);
//if self change ignore
if (mSelfChange) {
Log.i(TAG, "Ignoring self change");
mSelfChange = false;
return;
}
String phoneNumber = removeNonnumeric(editable.toString());
int stringLength = phoneNumber.length();
//empty case
if(stringLength == 0) {
mSelfChange = true;
editText.setText("");
return;
}
boolean startsWithOne = phoneNumber.charAt(0) == '1';
int maxLength = 10 + (startsWithOne ? 1 : 0);
//too large
if(stringLength > maxLength) {
Log.i(TAG, "String length is greater than max allowed, using previous string: " + previousNumber);
mSelfChange = true;
editText.setText(previousNumber);
Editable etext = editText.getText();
Selection.setSelection(etext, previousNumber.length());
return;
}
phoneNumber = formatPhoneNumber(phoneNumber);
if(previousNumber != null && phoneNumber.length() == previousNumber.length()) {
//user deleting last character, and it is a -
if(phoneNumber.endsWith("-")) {
phoneNumber = phoneNumber.substring(0, phoneNumber.length()-2);
}
}
mSelfChange = true;
previousNumber = phoneNumber;
editText.setText(phoneNumber);
Editable etext = editText.getText();
Selection.setSelection(etext, phoneNumber.length());
}
private String formatPhoneNumber(String phoneNumber) {
int stringLength = phoneNumber.length();
//check if starts with 1, if it does, dash index is increased by 1
boolean startsWithOne = phoneNumber.charAt(0) == '1';
//if the length of the string is 6, add another dash
int lastHyphenIndex = 6 + (startsWithOne ? 1 : 0);
if (stringLength >= lastHyphenIndex) {
phoneNumber = phoneNumber.substring(0, lastHyphenIndex) + "-" + phoneNumber.substring(lastHyphenIndex, phoneNumber.length());
}
//if the length of the string is 3, add a dash
int secondToLastHyphenIndex = 3 + (startsWithOne ? 1 : 0);
if (stringLength >= secondToLastHyphenIndex) {
phoneNumber = phoneNumber.substring(0, secondToLastHyphenIndex) + "-" + phoneNumber.substring(secondToLastHyphenIndex, phoneNumber.length());
}
//If the number starts with 1, add a dash after 1
if (phoneNumber.startsWith("1")) {
phoneNumber = phoneNumber.substring(0, 1) + "-" + phoneNumber.substring(1, phoneNumber.length());
}
return phoneNumber;
}
private static String removeNonnumeric(String text) {
return text.replaceAll("[^\\d]", "");
}
}

Related

Issue while removing automatically added characters to custom PhoneNumberTextWatcher (XXX) XXX-XXXX

My code is working fine when formatting text in (XXX) XXX-XXXX format. But when removing characters, it stops once reached to character -/(). If I again put cursor to any number characters -/() will automatically get removed.
Here is code I used.
public class PhoneNumberTextWatcher implements TextWatcher {
private static final String TAG = PhoneNumberTextWatcher.class
.getSimpleName();
private EditText edTxt;
private boolean isDelete;
public PhoneNumberTextWatcher(EditText edTxtPhone) {
this.edTxt = edTxtPhone;
edTxt.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
isDelete = true;
}
return false;
}
});
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
if (isDelete) {
isDelete = false;
return;
}
String val = s.toString();
String a = "";
String b = "";
String c = "";
if (val != null && val.length() > 0) {
val = val.replace("-", "");
val = val.replace("(", "");
val = val.replace(" ", "");
val = val.replace(")", "");
if (val.length() >= 3) {
a = val.substring(0, 3);
} else if (val.length() < 3) {
a = val.substring(0, val.length());
}
if (val.length() >= 6) {
b = val.substring(3, 6);
c = val.substring(6, val.length());
} else if (val.length() > 3 && val.length() < 6) {
b = val.substring(3, val.length());
}
StringBuffer stringBuffer = new StringBuffer();
if (a != null && a.length() > 0) {
if (a.length() == 3) {
stringBuffer.append("("+a+")"+" ");
}
else{
stringBuffer.append(a);
}
}
if (b != null && b.length() > 0) {
stringBuffer.append(b);
if (b.length() == 3) {
stringBuffer.append("-");
}
}
if (c != null && c.length() > 0) {
stringBuffer.append(c);
}
edTxt.removeTextChangedListener(this);
edTxt.setText(stringBuffer.toString());
edTxt.setSelection(edTxt.getText().toString().length());
edTxt.addTextChangedListener(this);
} else {
edTxt.removeTextChangedListener(this);
edTxt.setText("");
edTxt.addTextChangedListener(this);
}
}
}
No need to listen for Delete key. Just store the previous value of edittext and compare it with new when afterTextChanged is called. Code below works great in my project. I have modified it for (XXX) XXX-XXXX format. You can modify the logic to specify when to delete special characters (, ) and -.
PhoneNumberTextWatcher:
public class PhoneNumberTextWatcher implements TextWatcher {
private EditText phoneNumberEditText;
private String phoneNumber = "";
public PhoneNumberTextWatcher(EditText editText) {
phoneNumberEditText = editText;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable s) {
String newValue = s.toString();
if (newValue.length() > phoneNumber.length()) {
phoneNumber = s.toString();
if (phoneNumber.length() == 4) {
if ('(' != phoneNumber.charAt(0)) {
phoneNumberEditText.setText("(" + phoneNumber.substring(0, phoneNumber.length() - 1) + ") " + phoneNumber.substring(phoneNumber.length() - 1));
phoneNumberEditText.setSelection(phoneNumber.length());
}
} else if (phoneNumber.length() == 10) {
phoneNumberEditText.setText(phoneNumber.substring(0, phoneNumber.length() - 1) + "-" + phoneNumber.substring(phoneNumber.length() - 1));
phoneNumberEditText.setSelection(phoneNumber.length());
}
}
else if (newValue.length() < phoneNumber.length()) {
phoneNumber = s.toString();
if (phoneNumber.length() == 10) {
phoneNumberEditText.setText(phoneNumber.substring(0, phoneNumber.length() - 1));
phoneNumberEditText.setSelection(phoneNumber.length());
}
else if (phoneNumber.length() == 6) {
phoneNumberEditText.setText(phoneNumber.substring(1, phoneNumber.length() - 2));
phoneNumberEditText.setSelection(phoneNumber.length());
}
}
}
}

Android EditText InputFilter

How to delete two character at once with the filter?
I am trying to apply a simple filter to an EditText.
It must work as follows:
(want to receive format: 1234 5678....)
===> EDITED: First part works well.
1) when there are 4 digits in EditText and I am entering the 5-th digit -
first must appear a space and then this digit.
2) And I need a reverse for this (during characters deletion) -
the space must be deleted with the 5-th digit.
What is wrong with my code?
editText.setFilters(new InputFilter[]{new DigitsKeyListener(Boolean.FALSE, Boolean.TRUE) {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
// any chars except backspace
if (!source.equals("")) {
if (dest.length() == 4) {
// here I must add a space and then the source
// ===> EDITED:
return " " + source;
// return super.filter(" " + source, start, end + 1, dest, dstart, dend + 1);
} // backspace entered
} else {
if (dest.length() == 6) {
// here I must delete the 6-th character
// and the space before
return super.filter(source, 0, 0, dest, 5, 6);
}
}
return null;
}
}});
Please use this
public class CustomFormatWatcher implements TextWatcher {
private int size;
public CustomFormatWatcher(int size) {
this.size = size;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
char hyphen = ' ';
char c = 0;
if (editable.length() > 0) {
c = editable.charAt(editable.length() - 1);
if (c == hyphen) {
editable.delete(editable.length() - 1, editable.length());
}
}
if (editable.length() > 0 && (editable.length() % size) == 0) {
c = editable.charAt(editable.length() - 1);
if (hyphen == c) {
editable.delete(editable.length() - 1, editable.length());
}
}
if (editable.length() > 0 && (editable.length() % size) == 0) {
c = editable.charAt(editable.length() - 1);
// Only if its a digit where there should be a space we insert a hyphen
if (Character.isDigit(c) && TextUtils.split(editable.toString(), String.valueOf(hyphen)).length <= 3) {
editable.insert(editable.length() - 1, String.valueOf(hyphen));
}
}
}
}
and then use
myEditText.addTextChangedListener(new CustomFormatWatcher());
I suggest you to use TextWatcher to format your EditText input, because InputFilter is generally used for input restrictions, to decides what can be typed not to format the text.
You'll get your desired output with this code:
String mTextValue;
Character mLastChar = '\0'; // init with empty character
int mKeyDel;
myEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String eachBlock[] = myEditText.getText().toString().split(" ");
myEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL)
mKeyDel = 1;
return false;
}
});
if (mKeyDel == 0) {
if (((myEditText.getText().length() + 1) % 5) == 0) {
myEditText.setText(myEditText.getText() + " ");
myEditText.setSelection(myEditText.getText().length());
}
mTextValue = myEditText.getText().toString();
} else {
mTextValue = myEditText.getText().toString();
if (mLastChar.equals(' ')) {
mTextValue = mTextValue.substring(0, mTextValue.length() - 1);
myEditText.setText(mTextValue);
myEditText.setSelection(mTextValue.length());
}
mKeyDel = 0;
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (s.length()>0) {// save the last char value
mLastChar = s.charAt(s.length() - 1);
} else {
mLastChar = '\0';
}
}
#Override
public void afterTextChanged(Editable s) {}
});

Using keyListener and textChangedListener together in Android editText

I am trying to use both
editPhoneNumber.setKeyListener(new KeyListener()
and
editPhoneNumber.addTextChangedListener(new TextWatcher()
together but it seems that they block eachother, my editText is no longer editable.
Thanks for any help
Edit:
I am trying to format the input as the user types:
Input:5551112233
Formatted Input: (555) 111 22 33
The formatting part works well but the reason I am trying to add the KeyListener is when the user tries to delete (by pressing on delete key) and when the inputs length becomes -let's say- 12 characters TextChangedListener interrupts the user to delete by always putting a " " at he end of the text. That is why I am trying to disable the TextChangedListener when the input is a delete key.
boolean isResetClicked;
EditText editPhoneNumber;
Button buttonReset;
protected void onCreate(Bundle savedInstanceState)
{
editPhoneNumber = (EditText) findViewById(R.id.editPhoneNumber);
buttonReset = (Button) findViewById(R.id.buttonResetPhoneNumber);
buttonReset.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
isResetClicked = true;
editPhoneNumber.getText().clear();
isResetClicked = false;
}
});
editPhoneNumber.setKeyListener(new KeyListener()
{
#Override
public boolean onKeyUp(View view, Editable text, int keyCode,
KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_DEL)
{
isResetClicked = true;
}
else
isResetClicked=false;
return false;
}
#Override
public boolean onKeyOther(View view, Editable text, KeyEvent event)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onKeyDown(View view, Editable text, int keyCode,
KeyEvent event)
{
return false;
}
#Override
public int getInputType()
{
// TODO Auto-generated method stub
return 0;
}
#Override
public void clearMetaKeyState(View view, Editable content,
int states)
{
// TODO Auto-generated method stub
}
});
editPhoneNumber.addTextChangedListener(new TextWatcher()
{
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{
String str;
if (!isResetClicked)
{
if (s.length() == 0)
{
editPhoneNumber.setText("(");
}
if (s.length() == 1)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText("(" + str);
editPhoneNumber.setSelection(editPhoneNumber.getText()
.length());
}
if (s.length() == 4)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + ") ");
editPhoneNumber.setSelection(editPhoneNumber.getText()
.length());
}
if (s.length() == 9)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + " ");
editPhoneNumber.setSelection(editPhoneNumber.getText()
.length());
}
if (s.length() == 12)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + " ");
editPhoneNumber.setSelection(editPhoneNumber.getText()
.length());
}
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
{
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s)
{
}
});
Edit 2:
Even if I'm still unable to understand why two event listeners block my edittext, I solved my problem by modifying the code:
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{
String str;
/*Log.i("ED",
"LengthBefore before (lengthBefore = lengthAfter;): "
+ String.valueOf(lengthBefore));*/
lengthBefore = lengthAfter;
lengthAfter = s.length();
/*Log.i("ED",
"LengthBefore after (lengthBefore = lengthAfter;): "
+ String.valueOf(lengthBefore));*/
if ((lengthBefore < lengthAfter) || lengthBefore == 0)
{
if (!isResetClicked)
{
if (s.length() == 0)
{
editPhoneNumber.setText("(");
}
if (s.length() == 1)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText("(" + str);
editPhoneNumber.setSelection(editPhoneNumber
.getText().length());
}
if (s.length() == 4)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + ") ");
editPhoneNumber.setSelection(editPhoneNumber
.getText().length());
}
if (s.length() == 9)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + " ");
editPhoneNumber.setSelection(editPhoneNumber
.getText().length());
}
if (s.length() == 12)
{
str = editPhoneNumber.getText().toString();
editPhoneNumber.setText(str + " ");
editPhoneNumber.setSelection(editPhoneNumber
.getText().length());
}
}
}
lengthAfter = s.length();
/*Log.i("ED", "LengthAfter after (lengthAfter = s.length();): "
+ String.valueOf(lengthAfter));
Log.i("ED", "LengthBefore: " + String.valueOf(lengthBefore));
Log.i("ED", "LengthAfter: " + String.valueOf(lengthAfter));*/
}
As when the user tries to delete a character the new length will be shorter than the older one. So I prevented the code from checking the length by:
if ((lengthBefore < lengthAfter) || lengthBefore == 0)

EditText Social Security Number

I am developing one application in android for California. now i want to enter Social Security Number in Edit Text in xxx-xx-xxxx format. i have tried following code for achieve the functionality but it is not working fine for clearing the text.. following is my code. any help would be appreciated. i want auto format functionality.
etSocialSecurityNumber.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String text = etSocialSecurityNumber.getText().toString();
textlength = etSocialSecurityNumber.getText().length();
if(text.endsWith(" "))
return;
if(textlength == 4 || textlength == 7 )
{
etSocialSecurityNumber.setText(new StringBuilder(text).insert(text.length()-1, "-").toString());
etSocialSecurityNumber.setSelection(etSocialSecurityNumber.getText().length());
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
This will add a - after every 4 characters and it handels all kind of editing of user, just put your condition for 3 and 2 chars:
edit_text.addTextChangedListener(new TextWatcher() {
private boolean spaceDeleted;
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
CharSequence charDeleted = s.subSequence(start, start + count);
spaceDeleted = " ".equals(charDeleted.toString());
}
public void afterTextChanged(Editable editable) {
edit_text.removeTextChangedListener(this);
int cursorPosition = edit_text.getSelectionStart();
String withSpaces = formatText(editable);
edit_text.setText(withSpaces);
edit_text.setSelection(cursorPosition + (withSpaces.length() - editable.length()));
if (spaceDeleted) {
edit_text.setSelection(edit_text.getSelectionStart() - 1);
spaceDeleted = false;
}
edit_text.addTextChangedListener(this);
}
private String formatText(CharSequence text)
{
StringBuilder formatted = new StringBuilder();
int count = 0;
for (int i = 0; i < text.length(); ++i)
{
if (Character.isDigit(text.charAt(i)))
{
if (count % 4 == 0 && count > 0)
formatted.append("-");
formatted.append(text.charAt(i));
++count;
}
}
return formatted.toString();
}
});
Edited:
userNameET.addTextChangedListener(new TextWatcher() {
private boolean spaceDeleted;
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
CharSequence charDeleted = s.subSequence(start, start + count);
spaceDeleted = "-".equals(charDeleted.toString());
}
public void afterTextChanged(Editable editable) {
userNameET.removeTextChangedListener(this);
int cursorPosition = userNameET.getSelectionStart();
String withSpaces = formatText(editable);
userNameET.setText(withSpaces);
userNameET.setSelection(cursorPosition + (withSpaces.length() - editable.length()));
if (spaceDeleted) {
// userNameET.setSelection(userNameET.getSelectionStart() - 1);
spaceDeleted = false;
}
userNameET.addTextChangedListener(this);
}
private String formatText(CharSequence text)
{
StringBuilder formatted = new StringBuilder();
int count = 0;
if(text.length()==3||text.length()==6)
{
if (!spaceDeleted)
formatted.append(text+"-");
else
formatted.append(text);
}
else
formatted.append(text);
return formatted.toString();
}
});
The following Kotlin code sufficed my requirements
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
backspaced = count == 0
}
override fun afterTextChanged(s: Editable?) {
s?.apply {
if (!isEmpty()) {
if (get(lastIndex) != '-' && (length > 1 && get(lastIndex - 1) != '-') && !backspaced)
count { x -> x.isDigit() }.let { mapOf(3 to 3, 4 to 3, 5 to 6, 6 to 6)[it]?.let { index -> insert(index, "-") } }
else if ((get(lastIndex) == '-' && backspaced) || (lastIndexOf('-') in listOf(0,1,2,4,5,7,8,9,10)) )
delete(length - 1, length)
}
}
}
I know its too late to post an answer here. I just want to share the code which I used to format SSN. Try the following code.
public class SSNFormatter implements TextWatcher{
private boolean mFormatting;
private boolean clearFlag;
private int mLastStart;
private String mBeforeText;
private boolean spaceDeleted;
WeakReference<EditText> mWeakEditText;
public SSNFormatter(WeakReference<EditText> weakEditText) {
this.mWeakEditText = weakEditText;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
mLastStart = start;
mBeforeText = s.toString();
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length()>0 && mWeakEditText.get().getText().hashCode() == s.hashCode() && mWeakEditText.get().getError() != null)
mWeakEditText.get().setError(null);
if (!mFormatting) {
mFormatting = true;
int curPos = mLastStart;
String beforeValue = mBeforeText;
String currentValue = s.toString();
String formattedValue = formatSSN(s);
if (currentValue.length() > beforeValue.length()) {
int setCusorPos = formattedValue.length()
- (beforeValue.length() - curPos);
mWeakEditText.get().setSelection(
setCusorPos < 0 ? 0 : setCusorPos);
} else {
int setCusorPos = formattedValue.length()
- (currentValue.length() - curPos);
if (setCusorPos > 0
&& !Character.isDigit(formattedValue
.charAt(setCusorPos - 1))) {
setCusorPos--;
}
mWeakEditText.get().setSelection(
setCusorPos < 0 ? 0 : setCusorPos);
}
mFormatting = false;
}
}
private String formatSSN(Editable text){
StringBuilder formattedString = new StringBuilder();
// Remove everything except digits
int p = 0;
while (p < text.length()) {
char ch = text.charAt(p);
if (!Character.isDigit(ch)) {
text.delete(p, p + 1);
} else {
p++;
}
}
// Now only digits are remaining
String allDigitString = text.toString();
int totalDigitCount = allDigitString.length();
if (totalDigitCount == 0 || totalDigitCount > 10) {
// May be the total length of input length is greater than the
// expected value so we'll remove all formatting
text.clear();
text.append(allDigitString);
return allDigitString;
}
int alreadyPlacedDigitCount = 0;
// Only '1' is remaining and user pressed backspace and so we clear
// the edit text.
if (allDigitString.equals("1") && clearFlag) {
text.clear();
clearFlag = false;
return "";
}
boolean chang3 = true;
boolean chang2 = false;
// There must be a '-' inserted after the next 3 numbers
if (chang3 && totalDigitCount - alreadyPlacedDigitCount > 3) {
formattedString
.append(allDigitString.substring(alreadyPlacedDigitCount,
alreadyPlacedDigitCount + 3) + "-");
alreadyPlacedDigitCount += 3;
chang3 = false;
chang2 = true;
}
// There must be a '-' inserted after the next 2 numbers
if (chang2 && totalDigitCount - alreadyPlacedDigitCount > 2) {
formattedString
.append(allDigitString.substring(alreadyPlacedDigitCount,
alreadyPlacedDigitCount + 2) + "-");
alreadyPlacedDigitCount += 2;
chang3 = true;
chang2 = false;
}
// All the required formatting is done so we'll just copy the
// remaining digits.
if (totalDigitCount > alreadyPlacedDigitCount) {
formattedString.append(allDigitString
.substring(alreadyPlacedDigitCount));
}
text.clear();
text.append(formattedString.toString());
return formattedString.toString();
}
}

How to format person height in EditText to reflect inches and feet?

I have an EditText field in my app which is for person's height. How do I format it to make it look like say 5'9"? When a person types 5 the app should add ' by itself and when a person types 9 it should add ". How do I do that? Thank you.
Use this:
public class TextWatcherActivity extends Activity {
EditText e;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
e = (EditText) findViewById(R.id.editText1);
e.addTextChangedListener(new CustomTextWatcher(e));
}
}
class CustomTextWatcher implements TextWatcher {
private EditText mEditText;
public CustomTextWatcher(EditText e) {
mEditText = e;
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void afterTextChanged(Editable s) {
int count = s.length();
String str = s.toString();
if (count == 1) {
str = str + "'";
} else if (count == 2) {
return;
} else if (count == 3) {
str = str + "\"";
} else if (count >= 4) {
return;
}
mEditText.setText(str);
mEditText.setSelection(mEditText.getText().length());
}
}
Edit:
If user can insert one,two and more digit between ' and " change afterTextChanged in above code like this:
public void afterTextChanged(Editable s) {
int count = s.length();
String str = s.toString();
if (count == 1) {
str = str + "'";
} else if (count == 3) {
str = str + "\"";
} else if ((count > 4) && (str.charAt(str.length() - 1) != '\"') ){
str = str.substring(0, str.length() - 2) + str.charAt(str.length() - 1)
+ "\"";
} else {
return;
}
mEditText.setText(str);
mEditText.setSelection(mEditText.getText().length());
}
use this :
for delete "'".
mBinding.edtHeight.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
if (mBinding.edtHeight.getText().length() == 2) {
mBinding.edtHeight.setText("");
}
}
return false;
}
});

Categories

Resources