Created
September 23, 2015 00:38
-
-
Save alfredbaudisch/f4416061dd1858b1f4ee to your computer and use it in GitHub Desktop.
Android EditText mask for Brazilian telephone numbers. It deals with the default format (xx) xxxx-xxxx as well the newer longer one (xx) xxxxx-xxxx. Máscara de telefones brasileiros para EditText do Android: formata tanto o telefone padrão (xx) xxxx-xxxx, quanto o novo formato (xx) xxxxx-xxxx.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Adapted to BR phone format from the class | |
* UsPhoneNumberFormatter by Samik Bandyopadhyay: | |
* http://stackoverflow.com/a/23659268/332839 | |
*/ | |
public class BrPhoneNumberFormatter implements TextWatcher { | |
final int MAX_LENGTH = 11; | |
//This TextWatcher sub-class formats entered numbers as (41) 1234(5)?-6789 | |
private boolean mFormatting; // this is a flag which prevents the stack(onTextChanged) | |
private boolean clearFlag; | |
private int mLastStartLocation; | |
private String mLastBeforeText; | |
private WeakReference<EditText> mWeakEditText; | |
public BrPhoneNumberFormatter(WeakReference<EditText> weakEditText) { | |
this.mWeakEditText = weakEditText; | |
} | |
@Override | |
public void beforeTextChanged(CharSequence s, int start, int count, | |
int after) { | |
if (after == 0 && s.toString().equals("(")) { | |
clearFlag = true; | |
} | |
mLastStartLocation = start; | |
mLastBeforeText = s.toString(); | |
} | |
@Override | |
public void onTextChanged(CharSequence s, int start, int before, | |
int count) { | |
// TODO: Do nothing | |
} | |
@Override | |
public void afterTextChanged(Editable s) { | |
// Make sure to ignore calls to afterTextChanged | |
// caused by the work done below | |
if (!mFormatting) { | |
mFormatting = true; | |
int curPos = mLastStartLocation; | |
String beforeValue = mLastBeforeText; | |
String currentValue = s.toString(); | |
String formattedValue = formatUsNumber(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 formatUsNumber(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 > MAX_LENGTH) { | |
allDigitString = allDigitString.substring(0, MAX_LENGTH); | |
totalDigitCount--; | |
} | |
// Check if we are dealing with the new phone format, with an additional digit | |
boolean isLonger = totalDigitCount == MAX_LENGTH; | |
int dashAfter = isLonger ? 5 : 4; | |
if (totalDigitCount == 0 | |
|| (totalDigitCount > 11 && !allDigitString.startsWith("(")) | |
|| totalDigitCount > 12) { | |
// 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 ( is remaining and user pressed backspace and so we clear | |
// the edit text. | |
if (allDigitString.equals("(") && clearFlag) { | |
text.clear(); | |
clearFlag = false; | |
return ""; | |
} | |
// The first 2 numbers beyond ) must be enclosed in brackets "()" | |
if (totalDigitCount - alreadyPlacedDigitCount > 2) { | |
formattedString.append("(" | |
+ allDigitString.substring(alreadyPlacedDigitCount, | |
alreadyPlacedDigitCount + 2) + ") "); | |
alreadyPlacedDigitCount += 2; | |
} | |
// There must be a '-' inserted after the next 4 or 5 numbers | |
// (5 in case we are dealing with the new longer phone format: (xx) xxxxx-xxxx | |
if (totalDigitCount - alreadyPlacedDigitCount > dashAfter) { | |
formattedString.append(allDigitString.substring( | |
alreadyPlacedDigitCount, alreadyPlacedDigitCount + dashAfter) | |
+ "-"); | |
alreadyPlacedDigitCount += dashAfter; | |
} | |
// 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(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final EditText telephone = (EditText) findViewById(R.id.telephone); | |
BrPhoneNumberFormatter addLineNumberFormatter = new BrPhoneNumberFormatter(new WeakReference<EditText>(telephone)); | |
telephone.addTextChangedListener(addLineNumberFormatter); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment