Last active
April 29, 2016 18:35
-
-
Save ekursakov/a62cd08e5dbb65aa4b3d943f9404ab70 to your computer and use it in GitHub Desktop.
EditText with masked input for russian (+7) phone numbers
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
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