Skip to content

Instantly share code, notes, and snippets.

@TheReprator
Created January 8, 2016 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheReprator/87f14b78bcb12f37c37e to your computer and use it in GitHub Desktop.
Save TheReprator/87f14b78bcb12f37c37e to your computer and use it in GitHub Desktop.
Patterened edit text for any pattern in android
<declare-styleable name="PatternedEditText">
<attr name="pattern" format="string"/>
<attr name="specialChar" format="string"/>
<attr name="showPatternAsHint" format="boolean"/>
</declare-styleable>
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcelable;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.EditText;
import java.util.ArrayList;
import java.util.List;
import cl.dummy.R;
public class PatternedEditText extends EditText {
private String mSpecialChar;
private String mPattern;
private String mRawText = "";
private List<Integer> specilCharOccurancesPattern=null;
public PatternedEditText(Context context) {
super(context);
}
public PatternedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternedEditText);
mPattern = a.getString(R.styleable.PatternedEditText_pattern);
mSpecialChar = a.getString(R.styleable.PatternedEditText_specialChar);
if (mSpecialChar == null)
mSpecialChar = "#";
final Character character='-';
specilCharOccurancesPattern=new ArrayList<>();
int index = mPattern.indexOf(character);
while (index >= 0) {
specilCharOccurancesPattern.add(index);
index = mPattern.indexOf(character, index + 1);
}
boolean showHint = a.getBoolean(R.styleable.PatternedEditText_showPatternAsHint, false);
a.recycle();
setFilters(new InputFilter[]{new InputFilter.LengthFilter(mPattern.length())});
if (showHint)
setHint(mPattern);
final TextWatcher textWatcher = new TextWatcher() {
private boolean mForcing = false;
private StringBuilder sb;
private boolean isDeleting = false;
private int differenceCount = 0;
public int mBeforeTextLength = 0;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
mBeforeTextLength = s.length();
if (!mForcing) {
sb = new StringBuilder();
differenceCount = PatternUtils.getDifferenceCount(s.toString().substring(0, getSelectionStart()), mPattern, mSpecialChar.charAt(0));
sb.append(mRawText);
if (after == 0) {
isDeleting = true;
try {
sb.delete(getSelectionEnd() - count - differenceCount, getSelectionEnd() - differenceCount);
} catch (IndexOutOfBoundsException e) {
//Do nothing. User tried to delete unremovable char(s) of pattern.
}
} else
isDeleting = false;
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!mForcing) {
if (!isDeleting)
try {
int from = getSelectionEnd() - count - differenceCount;
if (from < 0)
from = 0;
sb.insert(from, s.subSequence(start, start + count));
} catch (StringIndexOutOfBoundsException e) {
Log.e("PatternedEditText: ", e.toString());
//getSelectionEnd() returns 0 after screen rotation.
//Added to handle filling EditText after rotation.
//onRestoreInstanceState() is responsible for setting text.
}
}
}
@Override
public void afterTextChanged(Editable s) {
if (!mForcing) {
mForcing = true;
mRawText = sb.toString();
String convertedText;
if (PatternUtils.isTextAppliesPattern(mRawText, mPattern, mSpecialChar.charAt(0))) {
convertedText = mRawText;
mRawText = PatternUtils.convertPatternedTextToText(mRawText, mPattern, mSpecialChar.charAt(0));
} else
convertedText = PatternUtils.convertTextToPatternedText(mRawText, mPattern, mSpecialChar.charAt(0));
int toBeSetCursorPosition = getSelectionStart();// + convertedText.length() - s.length();
if (mBeforeTextLength == 0)
toBeSetCursorPosition = convertedText.length();
s.clear();
s.append(convertedText);
if(specilCharOccurancesPattern.size()>0 && specilCharOccurancesPattern.contains(toBeSetCursorPosition-1))
if(isDeleting)
--toBeSetCursorPosition;
else
++toBeSetCursorPosition;
setSelection(toBeSetCursorPosition);
mForcing = false;
}
}
};
addTextChangedListener(textWatcher);
}
public PatternedEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setText(CharSequence text, BufferType type) {
this.mRawText = "";
super.setText(text, type);
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new PetSavedState(superState, mRawText);
}
@Override
public void onRestoreInstanceState(Parcelable state) {
PetSavedState savedState = (PetSavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
mRawText = savedState.getRealText();
setText(mRawText);
}
public String getRawText() {
return mRawText;
}
public String getSpecialChar() {
return mSpecialChar;
}
public void setSpecialChar(String specialChar) {
this.mSpecialChar = specialChar;
}
public String getPattern() {
return mPattern;
}
public void setPattern(String pattern) {
this.mPattern = pattern;
}
}
<cl.dummy.ui.custom_view.editext.pattern.PatternedEditText
pet:pattern="##"
android:inputType="number"
android:digits="0123456789"
android:tag="@string/fnewpost_jobFrom"
android:hint="@string/fnewpost_jobFrom"
android:layout_width="100dp"
android:layout_height="40dp"
android:id="@+id/fnewJB_ed_expfrom"/>
//It will accept only two number with input as number only
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment