Skip to content

Instantly share code, notes, and snippets.

@ekursakov
Last active April 29, 2016 18:35
Show Gist options
  • Save ekursakov/a62cd08e5dbb65aa4b3d943f9404ab70 to your computer and use it in GitHub Desktop.
Save ekursakov/a62cd08e5dbb65aa4b3d943f9404ab70 to your computer and use it in GitHub Desktop.
EditText with masked input for russian (+7) phone numbers
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
public class PhoneEditText extends EditText implements TextWatcher, View.OnFocusChangeListener {
private static final String PATTERN_NOT_NUMBERS = "[^0-9]*";
private static final String PATTERN_NUMBERS = "[0-9]*";
private static final String EMPTY = "";
private static final int COUNTRY_CODE = 7;
private static final String PLUS = "+";
private static final String MINUS = "-";
private static final String OPEN_BRACKET = "(";
private static final String CLOSE_BRACKET = ")";
private static final String SPACE = " ";
private static final int MAX_LENGTH = 11;
private static final int PART1_START = 1;
private static final int PART2_START = 4;
private static final int PART3_START = 7;
private static final int PART4_START = 9;
private boolean isUpdating;
private int currentPos;
public PhoneEditText(Context context, AttributeSet attrs) {
super(context, attrs);
addTextChangedListener(this);
setOnFocusChangeListener(this);
}
@Override
public void afterTextChanged(Editable s) {
if (s.length() == 0 || isUpdating) {
isUpdating = false;
return;
}
// extract number from text
String number = s.toString().replaceAll(PATTERN_NOT_NUMBERS, EMPTY);
if (number.length() > MAX_LENGTH)
number = number.substring(0, MAX_LENGTH);
int length = number.length();
StringBuilder result = new StringBuilder();
if (length > 0) {
result.append(PLUS + COUNTRY_CODE);
currentPos++;
}
if (length > PART1_START) {
result.append(SPACE + OPEN_BRACKET);
if (length >= PART2_START)
result.append(number.substring(PART1_START, PART2_START));
else
result.append(number.substring(PART1_START));
currentPos += 2;
}
if (length > PART2_START) {
result.append(CLOSE_BRACKET + SPACE);
if (length >= PART3_START)
result.append(number.substring(PART2_START, PART3_START));
else
result.append(number.substring(PART2_START));
currentPos += 2;
}
if (length > PART3_START) {
result.append(MINUS);
if (length >= PART4_START)
result.append(number.substring(PART3_START, PART4_START));
else
result.append(number.substring(PART3_START));
currentPos++;
}
if (length > PART4_START) {
result.append(MINUS);
if (length >= MAX_LENGTH)
result.append(number.substring(PART4_START, MAX_LENGTH));
else
result.append(number.substring(PART4_START));
currentPos++;
}
isUpdating = true;
setText(result);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (isUpdating) {
setSelection(currentPos);
} else {
final String number = s.toString().replaceAll(PATTERN_NUMBERS, EMPTY);
currentPos = start + count - number.length();
currentPos = (currentPos > MAX_LENGTH ? MAX_LENGTH : currentPos);
}
}
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (isEnabled()) {
String text = getText().toString();
if (text.length() == (PART1_START + 1)) {
setText(EMPTY);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment