diff --git a/MaskedEditText/build.gradle b/MaskedEditText/build.gradle
index e57534e..e52a469 100644
--- a/MaskedEditText/build.gradle
+++ b/MaskedEditText/build.gradle
@@ -5,20 +5,20 @@ plugins {
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
-String projectVersion = "1.0.5"
+String projectVersion = "1.0.6"
String projectGroup = "ru.egslava"
version = projectVersion
group = projectGroup
android {
- compileSdkVersion 25
- buildToolsVersion '25.0.2'
+ compileSdkVersion 26
+ buildToolsVersion '26.0.1'
defaultConfig {
- minSdkVersion 9
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 26
versionCode 1
versionName projectVersion
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -26,22 +26,22 @@ android {
}
dependencies {
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.android.support:appcompat-v7:25.2.0'
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:26.0.1'
- testCompile 'junit:junit:4.12'
+ testImplementation 'junit:junit:4.12'
}
// bintray deploy ....
String projectName = "edittext-mask"
String projectDescription = GFileUtils.readFile(new File("README.md"))
-String webUrl = "https://github.com/egslava/edittext-mask"
-String gitUrl = "https://github.com/egslava/edittext-mask.git"
+String webUrl = "https://github.com/edwardstock/edittext-mask"
+String gitUrl = "https://github.com/edwardstock/edittext-mask.git"
install {
@@ -105,25 +105,26 @@ artifacts {
archives sourcesJar
}
-bintray {
- user = bintrayUser
- key = bintrayApikey
-
- configurations = ['archives']
- pkg {
- repo = "maven"
- name = projectName
- userOrg = user
-// projectUrl = webUrl
- vcsUrl = gitUrl
- licenses = ["MIT"]
- group = projectGroup
- publish = true
-
- version {
- name = projectVersion
-// desc = projectDescription
- vcsTag = projectVersion
+if(hasProperty("bintrayUser") && hasProperty("bintrayApikey")) {
+ bintray {
+ user = bintrayUser
+ key = bintrayApikey
+
+ configurations = ['archives']
+ pkg {
+ repo = "maven"
+ name = projectName
+ userOrg = user
+ vcsUrl = gitUrl
+ licenses = ["MIT"]
+ group = projectGroup
+ publish = true
+
+ version {
+ name = projectVersion
+ vcsTag = projectVersion
+ }
}
}
-}
\ No newline at end of file
+}
+
diff --git a/MaskedEditText/src/androidTest/AndroidManifest.xml b/MaskedEditText/src/androidTest/AndroidManifest.xml
index bd876b8..10c1e25 100755
--- a/MaskedEditText/src/androidTest/AndroidManifest.xml
+++ b/MaskedEditText/src/androidTest/AndroidManifest.xml
@@ -5,12 +5,12 @@
android:versionName="1.0" >
+ android:minSdkVersion="14"
+ android:targetSdkVersion="26" />
+ android:theme="@style/Theme.AppCompat" />
\ No newline at end of file
diff --git a/MaskedEditText/src/main/java/br/com/sapereaude/maskedEditText/MaskedEditText.java b/MaskedEditText/src/main/java/br/com/sapereaude/maskedEditText/MaskedEditText.java
index 71776c7..981eb78 100755
--- a/MaskedEditText/src/main/java/br/com/sapereaude/maskedEditText/MaskedEditText.java
+++ b/MaskedEditText/src/main/java/br/com/sapereaude/maskedEditText/MaskedEditText.java
@@ -4,7 +4,7 @@
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Parcelable;
-import android.support.v4.text.TextUtilsCompat;
+import android.support.annotation.NonNull;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.SpannableStringBuilder;
@@ -21,381 +21,402 @@
public class MaskedEditText extends AppCompatEditText implements TextWatcher {
public static final String SPACE = " ";
+ protected int maxRawLength;
private String mask;
- private char charRepresentation;
- private boolean keepHint;
- private int[] rawToMask;
- private RawText rawText;
- private boolean editingBefore;
- private boolean editingOnChanged;
- private boolean editingAfter;
- private int[] maskToRaw;
- private int selection;
- private boolean initialized;
- private boolean ignore;
- protected int maxRawLength;
- private int lastValidMaskPosition;
- private boolean selectionChanged;
- private OnFocusChangeListener focusChangeListener;
+ private char charRepresentation;
+ private boolean keepHint;
+ private int[] rawToMask;
+ private RawText rawText;
+ private boolean editingBefore;
+ private boolean editingOnChanged;
+ private boolean editingAfter;
+ private int[] maskToRaw;
+ private int selection;
+ private boolean initialized;
+ private boolean ignore;
+ private int lastValidMaskPosition;
+ private boolean selectionChanged;
+ private OnFocusChangeListener focusChangeListener;
private String allowedChars;
private String deniedChars;
public MaskedEditText(Context context) {
- super(context);
- init();
- }
+ super(context);
+ init();
+ }
- public MaskedEditText(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
+ public MaskedEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
- TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MaskedEditText);
- mask = attributes.getString(R.styleable.MaskedEditText_mask);
+ TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MaskedEditText);
+ mask = attributes.getString(R.styleable.MaskedEditText_mask);
+ if (mask == null) mask = "";
allowedChars = attributes.getString(R.styleable.MaskedEditText_allowed_chars);
deniedChars = attributes.getString(R.styleable.MaskedEditText_denied_chars);
- String representation = attributes.getString(R.styleable.MaskedEditText_char_representation);
+ String representation = attributes.getString(R.styleable.MaskedEditText_char_representation);
- if(representation == null) {
- charRepresentation = '#';
- } else {
- charRepresentation = representation.charAt(0);
- }
+ if (representation == null) {
+ charRepresentation = '#';
+ } else {
+ charRepresentation = representation.charAt(0);
+ }
- keepHint = attributes.getBoolean(R.styleable.MaskedEditText_keep_hint, false);
+ keepHint = attributes.getBoolean(R.styleable.MaskedEditText_keep_hint, false);
- cleanUp();
+ cleanUp();
- // Ignoring enter key presses
- setOnEditorActionListener(new OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId,KeyEvent event) {
- switch (actionId) {
+ // Ignoring enter key presses
+ setOnEditorActionListener(new OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ switch (actionId) {
// case EditorInfo.IME_ACTION_NEXT:
- // fixing actionNext
+ // fixing actionNext
// return false;
- default:
- return true;
- }
- }
- });
- attributes.recycle();
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- final Parcelable superParcellable = super.onSaveInstanceState();
- final Bundle state = new Bundle();
- state.putParcelable("super", superParcellable);
- state.putString("text", getRawText());
- state.putBoolean("keepHint", isKeepHint());
- return state;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- Bundle bundle = (Bundle) state;
- keepHint = bundle.getBoolean("keepHint", false);
- super.onRestoreInstanceState(((Bundle) state).getParcelable("super"));
- final String text = bundle.getString("text");
-
- setText(text);
- Log.d(TAG, "onRestoreInstanceState: " + text);
- }
-
- @Override
- public void setText(CharSequence text, BufferType type) {
+ default:
+ return true;
+ }
+ }
+ });
+ attributes.recycle();
+ }
+
+ public MaskedEditText(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ final Parcelable superParcellable = super.onSaveInstanceState();
+ final Bundle state = new Bundle();
+ state.putParcelable("super", superParcellable);
+ state.putString("text", getRawText());
+ state.putBoolean("keepHint", isKeepHint());
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ Bundle bundle = (Bundle) state;
+ keepHint = bundle.getBoolean("keepHint", false);
+ super.onRestoreInstanceState(((Bundle) state).getParcelable("super"));
+ final String text = bundle.getString("text");
+
+ setText(text);
+ Log.d(TAG, "onRestoreInstanceState: " + text);
+ }
+
+ @Override
+ public void setText(CharSequence text, BufferType type) {
// if (text == null || text.equals("")) return;
- super.setText(text, type);
- }
+ super.setText(text, type);
+ }
- /** @param listener - its onFocusChange() method will be called before performing MaskedEditText operations,
- * related to this event. */
- @Override
- public void setOnFocusChangeListener(OnFocusChangeListener listener) {
- focusChangeListener = listener;
- }
+ /**
+ * @param listener - its onFocusChange() method will be called before performing MaskedEditText operations,
+ * related to this event.
+ */
+ @Override
+ public void setOnFocusChangeListener(OnFocusChangeListener listener) {
+ focusChangeListener = listener;
+ }
- private void cleanUp() {
- initialized = false;
+ private void cleanUp() {
+ initialized = false;
- generatePositionArrays();
+ generatePositionArrays();
- rawText = new RawText();
- selection = rawToMask[0];
+ if (rawToMask.length == 0) return;
+ rawText = new RawText();
+ selection = rawToMask[0];
- editingBefore = true;
- editingOnChanged = true;
- editingAfter = true;
- if(hasHint() && rawText.length() == 0) {
+ editingBefore = true;
+ editingOnChanged = true;
+ editingAfter = true;
+ if (hasHint() && rawText.length() == 0) {
this.setText(makeMaskedTextWithHint());
- } else {
+ } else {
this.setText(makeMaskedText());
- }
- editingBefore = false;
- editingOnChanged = false;
- editingAfter = false;
-
- maxRawLength = maskToRaw[previousValidPosition(mask.length() - 1)] + 1;
- lastValidMaskPosition = findLastValidMaskPosition();
- initialized = true;
-
- super.setOnFocusChangeListener(new OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (focusChangeListener != null) {
- focusChangeListener.onFocusChange(v, hasFocus);
- }
-
- if (hasFocus()) {
- selectionChanged = false;
- MaskedEditText.this.setSelection(lastValidPosition());
- }
- }
- });
- }
-
- private int findLastValidMaskPosition() {
- for(int i = maskToRaw.length - 1; i >= 0; i--) {
- if(maskToRaw[i] != -1) return i;
- }
- throw new RuntimeException("Mask must contain at least one representation char");
- }
-
- private boolean hasHint() {
- return getHint() != null;
- }
-
- public MaskedEditText(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
-
- public void setMask(String mask) {
- this.mask = mask;
- cleanUp();
- }
-
- public String getMask() {
- return this.mask;
- }
-
- public String getRawText() {
- return this.rawText.getText();
- }
-
- public void setCharRepresentation(char charRepresentation) {
- this.charRepresentation = charRepresentation;
- cleanUp();
- }
-
- public char getCharRepresentation() {
- return this.charRepresentation;
- }
+ }
+ editingBefore = false;
+ editingOnChanged = false;
+ editingAfter = false;
+
+ maxRawLength = maskToRaw[previousValidPosition(mask.length() - 1)] + 1;
+ lastValidMaskPosition = findLastValidMaskPosition();
+ initialized = true;
+
+ super.setOnFocusChangeListener(new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (focusChangeListener != null) {
+ focusChangeListener.onFocusChange(v, hasFocus);
+ }
+
+ if (hasFocus()) {
+ selectionChanged = false;
+ MaskedEditText.this.setSelection(lastValidPosition());
+ }
+ }
+ });
+ }
+
+ private int findLastValidMaskPosition() {
+ for (int i = maskToRaw.length - 1; i >= 0; i--) {
+ if (maskToRaw[i] != -1) return i;
+ }
+ throw new RuntimeException("Mask must contain at least one representation char");
+ }
+
+ private boolean hasHint() {
+ return getHint() != null;
+ }
+
+ public String getAllowedChars() {
+ return this.allowedChars;
+ }
+
+ public void setAllowedChars(String allowedChars) {
+ this.allowedChars = allowedChars;
+ }
+
+ public String getDeniedChars() {
+ return this.deniedChars;
+ }
+
+ public void setDeniedChars(String deniedChars) {
+ this.deniedChars = deniedChars;
+ }
+
+ public String getMask() {
+ return this.mask;
+ }
+
+ public void setMask(@NonNull String mask) {
+ //noinspection ConstantConditions
+ if (mask == null) throw new NullPointerException("Mask can't be null");
+ this.mask = mask;
+ cleanUp();
+ }
+
+ public String getRawText() {
+ return this.rawText.getText();
+ }
+
+ public char getCharRepresentation() {
+ return this.charRepresentation;
+ }
+
+ public void setCharRepresentation(char charRepresentation) {
+ this.charRepresentation = charRepresentation;
+ cleanUp();
+ }
/**
- * Generates positions for values characters. For instance:
- * Input data: mask = "+7(###)###-##-##
- * After method execution:
- * rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
- * maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
- * charsInMask = "+7()- " (and space, yes)
+ * Generates positions for values characters. For instance:
+ * Input data: mask = "+7(###)###-##-##
+ * After method execution:
+ * rawToMask = [3, 4, 5, 6, 8, 9, 11, 12, 14, 15]
+ * maskToRaw = [-1, -1, -1, 0, 1, 2, -1, 3, 4, 5, -1, 6, 7, -1, 8, 9]
+ * charsInMask = "+7()- " (and space, yes)
*/
- private void generatePositionArrays() {
- int[] aux = new int[mask.length()];
- maskToRaw = new int[mask.length()];
- String charsInMaskAux = "";
-
- int charIndex = 0;
- for(int i = 0; i < mask.length(); i++) {
- char currentChar = mask.charAt(i);
- if(currentChar == charRepresentation) {
- aux[charIndex] = i;
- maskToRaw[i] = charIndex++;
- }
- else {
- String charAsString = Character.toString(currentChar);
- if(!charsInMaskAux.contains(charAsString)) {
- charsInMaskAux = charsInMaskAux.concat(charAsString);
- }
- maskToRaw[i] = -1;
- }
- }
- if(charsInMaskAux.indexOf(' ') < 0) {
- charsInMaskAux = charsInMaskAux + SPACE;
- }
-
- char[] charsInMask = charsInMaskAux.toCharArray();
-
- rawToMask = new int[charIndex];
- for (int i = 0; i < charIndex; i++) {
- rawToMask[i] = aux[i];
- }
- }
-
- private void init() {
- addTextChangedListener(this);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
- if(!editingBefore) {
- editingBefore = true;
- if(start > lastValidMaskPosition) {
- ignore = true;
- }
- int rangeStart = start;
- if(after == 0) {
- rangeStart = erasingStart(start);
- }
- Range range = calculateRange(rangeStart, start + count);
- if(range.getStart() != -1) {
- rawText.subtractFromString(range);
- }
- if(count > 0) {
- selection = previousValidPosition(start);
- }
- }
- }
-
- private int erasingStart(int start) {
- while(start > 0 && maskToRaw[start] == -1) {
- start--;
- }
- return start;
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- if(!editingOnChanged && editingBefore) {
- editingOnChanged = true;
- if(ignore) {
- return;
- }
- if(count > 0) {
- int startingPosition = maskToRaw[nextValidPosition(start)];
- String addedString = s.subSequence(start, start + count).toString();
- count = rawText.addToString(clear(addedString), startingPosition, maxRawLength);
- if(initialized) {
- int currentPosition;
- if(startingPosition + count < rawToMask.length)
- currentPosition = rawToMask[startingPosition + count];
- else
- currentPosition = lastValidMaskPosition + 1;
- selection = nextValidPosition(currentPosition);
- }
- }
- }
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if(!editingAfter && editingBefore && editingOnChanged) {
- editingAfter = true;
+ private void generatePositionArrays() {
+ int[] aux = new int[mask.length()];
+ maskToRaw = new int[mask.length()];
+ String charsInMaskAux = "";
+
+ int charIndex = 0;
+ for (int i = 0; i < mask.length(); i++) {
+ char currentChar = mask.charAt(i);
+ if (currentChar == charRepresentation) {
+ aux[charIndex] = i;
+ maskToRaw[i] = charIndex++;
+ } else {
+ String charAsString = Character.toString(currentChar);
+ if (!charsInMaskAux.contains(charAsString)) {
+ charsInMaskAux = charsInMaskAux.concat(charAsString);
+ }
+ maskToRaw[i] = -1;
+ }
+ }
+ if (charsInMaskAux.indexOf(' ') < 0) {
+ charsInMaskAux = charsInMaskAux + SPACE;
+ }
+
+ char[] charsInMask = charsInMaskAux.toCharArray();
+
+ rawToMask = new int[charIndex];
+ for (int i = 0; i < charIndex; i++) {
+ rawToMask[i] = aux[i];
+ }
+ }
+
+ private void init() {
+ addTextChangedListener(this);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ if (!editingBefore) {
+ editingBefore = true;
+ if (start > lastValidMaskPosition) {
+ ignore = true;
+ }
+ int rangeStart = start;
+ if (after == 0) {
+ rangeStart = erasingStart(start);
+ }
+ Range range = calculateRange(rangeStart, start + count);
+ if (range.getStart() != -1) {
+ rawText.subtractFromString(range);
+ }
+ if (count > 0) {
+ selection = previousValidPosition(start);
+ }
+ }
+ }
+
+ private int erasingStart(int start) {
+ while (start > 0 && maskToRaw[start] == -1) {
+ start--;
+ }
+ return start;
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ if (!editingOnChanged && editingBefore) {
+ editingOnChanged = true;
+ if (ignore) {
+ return;
+ }
+ if (count > 0) {
+ int startingPosition = maskToRaw[nextValidPosition(start)];
+ String addedString = s.subSequence(start, start + count).toString();
+ count = rawText.addToString(clear(addedString), startingPosition, maxRawLength);
+ if (initialized) {
+ int currentPosition;
+ if (startingPosition + count < rawToMask.length)
+ currentPosition = rawToMask[startingPosition + count];
+ else
+ currentPosition = lastValidMaskPosition + 1;
+ selection = nextValidPosition(currentPosition);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (!editingAfter && editingBefore && editingOnChanged) {
+ editingAfter = true;
if (hasHint() && (keepHint || rawText.length() == 0)) {
setText(makeMaskedTextWithHint());
- } else {
+ } else {
setText(makeMaskedText());
}
- selectionChanged = false;
- setSelection(selection);
+ selectionChanged = false;
+ setSelection(selection);
- editingBefore = false;
- editingOnChanged = false;
- editingAfter = false;
- ignore = false;
- }
- }
+ editingBefore = false;
+ editingOnChanged = false;
+ editingAfter = false;
+ ignore = false;
+ }
+ }
- public boolean isKeepHint() {
- return keepHint;
- }
+ public boolean isKeepHint() {
+ return keepHint;
+ }
- public void setKeepHint(boolean keepHint) {
- this.keepHint = keepHint;
- setText(getRawText());
- }
+ public void setKeepHint(boolean keepHint) {
+ this.keepHint = keepHint;
+ setText(getRawText());
+ }
- @Override
- protected void onSelectionChanged(int selStart, int selEnd) {
- // On Android 4+ this method is being called more than 1 time if there is a hint in the EditText, what moves the cursor to left
- // Using the boolean var selectionChanged to limit to one execution
+ @Override
+ protected void onSelectionChanged(int selStart, int selEnd) {
+ // On Android 4+ this method is being called more than 1 time if there is a hint in the EditText, what moves the cursor to left
+ // Using the boolean var selectionChanged to limit to one execution
- if(initialized ){
- if(!selectionChanged) {
+ if (initialized) {
+ if (!selectionChanged) {
selStart = fixSelection(selStart);
selEnd = fixSelection(selEnd);
- // exactly in this order. If getText.length() == 0 then selStart will be -1
- if (selStart > getText().length()) selStart = getText().length();
- if (selStart < 0) selStart = 0;
-
- // exactly in this order. If getText.length() == 0 then selEnd will be -1
- if (selEnd > getText().length()) selEnd = getText().length();
- if (selEnd < 0) selEnd = 0;
-
- setSelection(selStart, selEnd);
- selectionChanged = true;
- } else{
- //check to see if the current selection is outside the already entered text
- if(selStart > rawText.length() - 1){
- final int start = fixSelection(selStart);
- final int end = fixSelection(selEnd);
- if (start >= 0 && end < getText().length()){
- setSelection(start, end);
- }
- }
- }
- }
- super.onSelectionChanged(selStart, selEnd);
- }
-
- private int fixSelection(int selection) {
- if(selection > lastValidPosition()) {
- return lastValidPosition();
- } else {
- return nextValidPosition(selection);
- }
- }
-
- private int nextValidPosition(int currentPosition) {
- while(currentPosition < lastValidMaskPosition && maskToRaw[currentPosition] == -1) {
- currentPosition++;
- }
- if(currentPosition > lastValidMaskPosition) return lastValidMaskPosition + 1;
- return currentPosition;
- }
-
- private int previousValidPosition(int currentPosition) {
- while(currentPosition >= 0 && maskToRaw[currentPosition] == -1) {
- currentPosition--;
- if(currentPosition < 0) {
- return nextValidPosition(0);
- }
- }
- return currentPosition;
- }
-
- private int lastValidPosition() {
- if(rawText.length() == maxRawLength) {
- return rawToMask[rawText.length() - 1] + 1;
- }
- return nextValidPosition(rawToMask[rawText.length()]);
- }
-
-
- private String makeMaskedText() {
+ // exactly in this order. If getText.length() == 0 then selStart will be -1
+ if (selStart > getText().length()) selStart = getText().length();
+ if (selStart < 0) selStart = 0;
+
+ // exactly in this order. If getText.length() == 0 then selEnd will be -1
+ if (selEnd > getText().length()) selEnd = getText().length();
+ if (selEnd < 0) selEnd = 0;
+
+ setSelection(selStart, selEnd);
+ selectionChanged = true;
+ } else {
+ //check to see if the current selection is outside the already entered text
+ if (selStart > rawText.length() - 1) {
+ final int start = fixSelection(selStart);
+ final int end = fixSelection(selEnd);
+ if (start >= 0 && end < getText().length()) {
+ setSelection(start, end);
+ }
+ }
+ }
+ }
+ super.onSelectionChanged(selStart, selEnd);
+ }
+
+ private int fixSelection(int selection) {
+ if (selection > lastValidPosition()) {
+ return lastValidPosition();
+ } else {
+ return nextValidPosition(selection);
+ }
+ }
+
+ private int nextValidPosition(int currentPosition) {
+ while (currentPosition < lastValidMaskPosition && maskToRaw[currentPosition] == -1) {
+ currentPosition++;
+ }
+ if (currentPosition > lastValidMaskPosition) return lastValidMaskPosition + 1;
+ return currentPosition;
+ }
+
+ private int previousValidPosition(int currentPosition) {
+ while (currentPosition >= 0 && maskToRaw[currentPosition] == -1) {
+ currentPosition--;
+ if (currentPosition < 0) {
+ return nextValidPosition(0);
+ }
+ }
+ return currentPosition;
+ }
+
+ private int lastValidPosition() {
+ if (rawText.length() == maxRawLength) {
+ return rawToMask[rawText.length() - 1] + 1;
+ }
+ return nextValidPosition(rawToMask[rawText.length()]);
+ }
+
+
+ private String makeMaskedText() {
int maskedTextLength;
if (rawText.length() < rawToMask.length) {
maskedTextLength = rawToMask[rawText.length()];
} else {
maskedTextLength = mask.length();
}
- char[] maskedText = new char[maskedTextLength]; //mask.replace(charRepresentation, ' ').toCharArray();
+ char[] maskedText = new char[maskedTextLength]; //mask.replace(charRepresentation, ' ').toCharArray();
for (int i = 0; i < maskedText.length; i++) {
int rawIndex = maskToRaw[i];
if (rawIndex == -1) {
@@ -404,14 +425,14 @@ private String makeMaskedText() {
maskedText[i] = rawText.charAt(rawIndex);
}
}
- return new String(maskedText);
- }
+ return new String(maskedText);
+ }
private CharSequence makeMaskedTextWithHint() {
SpannableStringBuilder ssb = new SpannableStringBuilder();
int mtrv;
int maskFirstChunkEnd = rawToMask[0];
- for(int i = 0; i < mask.length(); i++) {
+ for (int i = 0; i < mask.length(); i++) {
mtrv = maskToRaw[i];
if (mtrv != -1) {
if (mtrv < rawText.length()) {
@@ -430,40 +451,40 @@ private CharSequence makeMaskedTextWithHint() {
return ssb;
}
- private Range calculateRange(int start, int end) {
- Range range = new Range();
- for(int i = start; i <= end && i < mask.length(); i++) {
- if(maskToRaw[i] != -1) {
- if(range.getStart() == -1) {
- range.setStart(maskToRaw[i]);
- }
- range.setEnd(maskToRaw[i]);
- }
- }
- if(end == mask.length()) {
- range.setEnd(rawText.length());
- }
- if(range.getStart() == range.getEnd() && start < end) {
- int newStart = previousValidPosition(range.getStart() - 1);
- if(newStart < range.getStart()) {
- range.setStart(newStart);
- }
- }
- return range;
- }
-
- private String clear(String string) {
- if (deniedChars != null){
- for(char c: deniedChars.toCharArray()){
- string = string.replace(Character.toString(c), "");
+ private Range calculateRange(int start, int end) {
+ Range range = new Range();
+ for (int i = start; i <= end && i < mask.length(); i++) {
+ if (maskToRaw[i] != -1) {
+ if (range.getStart() == -1) {
+ range.setStart(maskToRaw[i]);
+ }
+ range.setEnd(maskToRaw[i]);
+ }
+ }
+ if (end == mask.length()) {
+ range.setEnd(rawText.length());
+ }
+ if (range.getStart() == range.getEnd() && start < end) {
+ int newStart = previousValidPosition(range.getStart() - 1);
+ if (newStart < range.getStart()) {
+ range.setStart(newStart);
+ }
+ }
+ return range;
+ }
+
+ private String clear(String string) {
+ if (deniedChars != null) {
+ for (char c : deniedChars.toCharArray()) {
+ string = string.replace(Character.toString(c), "");
}
}
- if (allowedChars != null){
+ if (allowedChars != null) {
StringBuilder builder = new StringBuilder(string.length());
- for(char c: string.toCharArray() ){
- if (allowedChars.contains(String.valueOf(c) )){
+ for (char c : string.toCharArray()) {
+ if (allowedChars.contains(String.valueOf(c))) {
builder.append(c);
}
}
@@ -471,6 +492,6 @@ private String clear(String string) {
string = builder.toString();
}
- return string;
- }
+ return string;
+ }
}
diff --git a/README.md b/README.md
index 25f8c30..a702a74 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# MaskedEditText
-[![Download](https://api.bintray.com/packages/egorenkov/maven/edittext-mask/images/download.svg) ](https://bintray.com/egorenkov/maven/edittext-mask/_latestVersion) [![Build Status](https://travis-ci.org/egslava/edittext-mask.svg?branch=master)](https://travis-ci.org/egslava/edittext-mask)
+[![](https://jitpack.io/v/edwardstock/edittext-mask.svg)](https://jitpack.io/#edwardstock/edittext-mask)
![MaskedEditText - the library for masked input of phone numbers, social security numbers and so on for Android](publish/README.gif)
@@ -23,17 +23,22 @@ MaskedEditText is a simple Android EditText with customizable input mask support
For instance, you need user specified his phone in format +7(XXX)XXX-XX-XX. You also know user should have the only possibility to write digits but minuses, brackets and "+7" should appear automatically.
### Usage
-
Add this to your `build.gradle` :
```groovy
-compile 'ru.egslava:MaskedEditText:1.0.5'
+compile 'com.github.edwardstock:edittext-mask:1.0.7'
```
+
+Or for android gradle plugin >= 3.0 (beta or preview)
+```groovy
+implementation 'com.github.edwardstock:edittext-mask:1.0.7'
+```
+
Or download project and plug it in as a library.
Add _xmlns:mask="http://schemas.android.com/apk/res-auto"_ to your layout xml root:
-
-
+ mask:keep_hint="true"
+ />
+```
+
Where _mask_ is the input mask you want and '#' is an editable position (will be replaced by a whitespace on screen).
You can optionally set the representation character (in case you don't want to use '#'):
-
-
-
+```
You can also change the mask and the representation character programatically:
-
- MaskedEditText editText = (MaskedEditText) findViewById(R.id.my_edit_text)
- // Setting the representation character to '$'
- editText.setCharRepresentation('$');
- // Logging the representation character
- Log.i("Representation character", editText.getCharRepresentation());
- // Setting the mask
- editText.setMask("##/##/####");
- // Logging the mask
- Log.i("Mask", editText.getMask());
-
+```java
+import br.com.sapereaude.maskedEditText.MakedEditText;
+
+class MyActivity extends Activity {
+
+ void onCreate(Bundle savedInstance) {
+
+ MaskedEditText editText = (MaskedEditText) findViewById(R.id.my_edit_text);
+ // Setting the representation character to '$'
+ editText.setCharRepresentation('$');
+ // Logging the representation character
+ Log.i("Representation character", editText.getCharRepresentation());
+ // Setting the mask
+ editText.setMask("##/##/####");
+ // Settings allowed chars
+ editText.setAllowedChars("0123456789");
+ // Settings denied chars
+ editText.setDeniedChars("_ "); // underscore, whitespace
+ // Logging the mask
+ Log.i("Mask", editText.getMask());
+
+ }
+}
+```
*************************************************************************************************
## ru_RU
@@ -78,7 +98,7 @@ MaskedEditText - это всего лишь EditText, но с возможнос
Вписать в `build.gradle`:
```groovy
-compile 'ru.egslava:MaskedEditText:1.0.5'
+compile 'com.github.edwardstock:edittext-mask:1.0.7'
```
или скачать проект и подключить как библиотеку.
@@ -93,7 +113,7 @@ compile 'ru.egslava:MaskedEditText:1.0.5'
mask:allowed_chars="1234567890"
mask:mask="+7(###)###-##-##"
android:hint="1234567890"
- app:keep_hint="true"
+ mask:keep_hint="true"
/>
_mask_ задаёт требуемую маску, символ '#' задаёт редактируемую позицию (и будет заменён на пробел на экране).
@@ -108,13 +128,28 @@ _mask_ задаёт требуемую маску, символ '#' задаёт
/>
Кроме того, всё тоже самое можно сделать и программно:
-
- MaskedEditText editText = (MaskedEditText) findViewById(R.id.my_edit_text)
- // Setting the representation character to '$'
- editText.setCharRepresentation('$');
- // Logging the representation character
- Log.i("Representation character", editText.getCharRepresentation());
- // Setting the mask
- editText.setMask("##/##/####");
- // Logging the mask
- Log.i("Mask", editText.getMask());
+```java
+import br.com.sapereaude.maskedEditText.MakedEditText;
+
+class MyActivity extends Activity {
+
+ void onCreate(Bundle savedInstance) {
+
+ MaskedEditText editText = (MaskedEditText) findViewById(R.id.my_edit_text);
+ // Setting the representation character to '$'
+ editText.setCharRepresentation('$');
+ // Logging the representation character
+ Log.i("Representation character", editText.getCharRepresentation());
+ // Setting the mask
+ editText.setMask("##/##/####");
+ // Settings allowed chars
+ editText.setAllowedChars("0123456789");
+ // Settings denied chars
+ editText.setDeniedChars("_ "); // underscore, whitespace
+ // Logging the mask
+ Log.i("Mask", editText.getMask());
+
+ }
+}
+```
+
diff --git a/app/build.gradle b/app/build.gradle
index 0a82ff0..9971e73 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion '25.0.2'
+ compileSdkVersion 26
+ buildToolsVersion '26.0.1'
defaultConfig {
applicationId "ru.egslava.edittextphonenumber"
- minSdkVersion 9
- targetSdkVersion 25
+ minSdkVersion 14
+ targetSdkVersion 26
versionCode 1
versionName "1.0.0"
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
@@ -21,10 +21,10 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.android.support:appcompat-v7:25.2.0'
- compile project(':MaskedEditText')
- androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2', {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:26.0.1'
+ implementation project(':MaskedEditText')
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
}
}
diff --git a/app/src/main/java/ru/egslava/edittextphonenumber/MainActivity.java b/app/src/main/java/ru/egslava/edittextphonenumber/MainActivity.java
index 81443b0..350d7b5 100644
--- a/app/src/main/java/ru/egslava/edittextphonenumber/MainActivity.java
+++ b/app/src/main/java/ru/egslava/edittextphonenumber/MainActivity.java
@@ -1,24 +1,19 @@
package ru.egslava.edittextphonenumber;
-import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
-import android.text.InputFilter;
-import android.text.Spanned;
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.EditText;
-
import br.com.sapereaude.maskedEditText.MaskedEditText;
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- MaskedEditText phone = (MaskedEditText)findViewById(R.id.phone_input);
+ MaskedEditText phone = findViewById(R.id.phone_input);
}
@Override
diff --git a/build.gradle b/build.gradle
index 0b9dbcf..b9d34aa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,19 +3,16 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.3'
-// classpath 'com.github.dcendents:android-maven-plugin:1.2'
- // https://mvnrepository.com/artifact/com.github.dcendents/android-maven-gradle-plugin
+ classpath 'com.android.tools.build:gradle:3.0.0-beta2'
classpath group: 'com.github.dcendents', name: 'android-maven-gradle-plugin', version: '1.5'
-// classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0'
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
+ google()
}
}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fab72e1..198fa73 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Wed Aug 16 12:33:31 MSK 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip