Created
April 19, 2018 17:29
-
-
Save orcchg/b1656ace61b78b51dd93a4a3ef0d24a0 to your computer and use it in GitHub Desktop.
TextWatcher for expiry date MM/YY automatically adding slash. For Android
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.graphics.Canvas; | |
import android.graphics.Paint; | |
import android.support.annotation.NonNull; | |
import android.text.Editable; | |
import android.text.Spannable; | |
import android.text.TextWatcher; | |
import android.text.style.ReplacementSpan; | |
public class ExpiryDateTextWatcher implements TextWatcher { | |
private int maxLength = 5; | |
private boolean internalStopFormatFlag; | |
public ExpiryDateTextWatcher() {} | |
@Override | |
public void beforeTextChanged(CharSequence s, int start, int count, int after) { | |
} | |
@Override | |
public void onTextChanged(CharSequence s, int start, int before, int count) { | |
} | |
@Override | |
public void afterTextChanged(Editable s) { | |
if (internalStopFormatFlag) { | |
return; | |
} | |
internalStopFormatFlag = true; | |
formatExpiryDate(s, maxLength); | |
internalStopFormatFlag = false; | |
} | |
public static void formatExpiryDate(@NonNull Editable expiryDate, int maxLength) { | |
int textLength = expiryDate.length(); | |
// first remove any previous span | |
SlashSpan[] spans = expiryDate.getSpans(0, expiryDate.length(), SlashSpan.class); | |
for (int i = 0; i < spans.length; ++i) { | |
expiryDate.removeSpan(spans[i]); | |
} | |
// then truncate to max length | |
if (maxLength > 0 && textLength > maxLength - 1) { | |
expiryDate.replace(maxLength, textLength, ""); | |
--textLength; | |
} | |
// finally add margin spans | |
for (int i = 1; i <= ((textLength - 1) / 2); ++i) { | |
int end = i * 2 + 1; | |
int start = end - 1; | |
SlashSpan marginSPan = new SlashSpan(); | |
expiryDate.setSpan(marginSPan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); | |
} | |
} | |
public static class SlashSpan extends ReplacementSpan { | |
public SlashSpan() {} | |
@Override | |
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { | |
float[] widths = new float[end - start]; | |
float[] slashWidth = new float[1]; | |
paint.getTextWidths(text, start, end, widths); | |
paint.getTextWidths("/", slashWidth); | |
int sum = (int) slashWidth[0]; | |
for (int i = 0; i < widths.length; ++i) { | |
sum += widths[i]; | |
} | |
return sum; | |
} | |
@Override | |
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { | |
String xtext = "/" + text.subSequence(start, end); | |
canvas.drawText(xtext, 0, xtext.length(), x, y, paint); | |
} | |
} | |
} |
@milaptank Hello Please user below class to format date,
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import java.util.Calendar;
import java.util.Date;
public class DateMask implements TextWatcher {
private final static String TAG = DateMask.class.getSimpleName();
private String currentString = "";
private String separator = "/";
private DateMaskingCallback dateMaskingCallback;
private static final String INVALID_DATE_MSG = "Enter valid Date";
private static final String INVALID_MONTH_MSG = "Enter valid Month";
public DateMask(DateMaskingCallback dateMaskingCallback, String separator) {
this.dateMaskingCallback = dateMaskingCallback;
this.separator = separator;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int before, int count) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try {
String dateString = s.toString();
Log.e(TAG, "date current string "+currentString);
if (!currentString.equalsIgnoreCase(dateString)) {
currentString = dateString;
String errorString = "";
if (dateString.length() == 2 && before == 0) {
if (dateString.equalsIgnoreCase("00")) {
errorString = INVALID_MONTH_MSG;
} else if (Integer.parseInt(dateString) < 1 || Integer.parseInt(dateString) > 12) {
errorString = INVALID_MONTH_MSG;
}
} else if (dateString.length() == 3 && before == 0) {
String day = dateString.substring(2, dateString.length()-1);
dateString = dateString.substring(0,2)+separator+day;
} else if (dateString.length() == 4 && before == 0) {
String month = dateString.substring(3, 4);
if (Integer.parseInt(month) > 12) {
errorString = INVALID_DATE_MSG;
}
} else if (dateString.length() == 6 && before == 0) {
String yearString = dateString.substring(3,5);
dateString = dateString.substring(0, 3)+ yearString+separator;
if (yearString.startsWith("0")) {
errorString = "Please start year with > 0";
}
} else if (dateString.length() >= 7 && before == 0) {
Date currentDate = Calendar.getInstance().getTime();
Date enteredDate = new Date(dateString);
if (dateString.length() >= 10 && currentDate.getTime() < enteredDate.getTime()) {
errorString = "Future dates are not valid in dob";
}
}
Log.e(TAG, "dateString "+dateString +" error String "+errorString);
if (errorString.isEmpty()) {
dateMaskingCallback.dateOfBirthValidation(true, dateString, errorString);
} else {
dateMaskingCallback.dateOfBirthValidation(false, dateString, errorString);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void afterTextChanged(Editable editable) {
}
public interface DateMaskingCallback {
void dateOfBirthValidation(final boolean isValid, final String dateOfBirth, final String error) throws Exception;
}
}
// Usage is like below
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final EditText dob = findViewById(R.id.etDob);
dob.addTextChangedListener(new DateMask(new DateMask.DateMaskingCallback() {
@Override
public void dateOfBirthValidation(boolean isValid, String dateOfBirth, String error) throws Exception {
if (isValid) {
// sets formatted string here
dob.setText(dateOfBirth);
dob.setSelection(dateOfBirth.length());
} else {
// sets error here
dob.setError(error);
}
[}](url)
}, "/"));
}
@sumanpula thank you so much I will implement and let you know
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wants to change date format to
Dd/mm/yyyy
Then what's changes ??