diff --git a/README.MD b/README.MD
index 77fffd8..748f1fc 100755
--- a/README.MD
+++ b/README.MD
@@ -90,6 +90,7 @@ as your code is likely to use a different version from the library.
app:pinLineStrokeSelected="4dp" //the stroke (height) of the bottom line when field is focused.
app:pinBackgroundIsSquare="true|false" //optional, if you want the background drawable to be a square or circle width of each digit will be set to match the height of the widget.
app:pinLineColors="@color/pin_line_colors" //optional
+ app:pinSkipMaskLastChar="false" // optional, default false, if you want to show the last typed digit without the mask set it to "true"
android:layoutDirection="ltr|rtl"
/>
```
diff --git a/pinentryedittext/src/main/java/com/alimuzaffar/lib/pin/PinEntryEditText.java b/pinentryedittext/src/main/java/com/alimuzaffar/lib/pin/PinEntryEditText.java
index 09e4952..693e950 100755
--- a/pinentryedittext/src/main/java/com/alimuzaffar/lib/pin/PinEntryEditText.java
+++ b/pinentryedittext/src/main/java/com/alimuzaffar/lib/pin/PinEntryEditText.java
@@ -28,6 +28,8 @@
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
@@ -49,6 +51,7 @@ public class PinEntryEditText extends AppCompatEditText {
private static final String XML_NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android";
public static final String DEFAULT_MASK = "\u25CF";
+ public static final int HIDE_LAST_CHAR_MILLIS = 600;
protected String mMask = null;
protected StringBuilder mMaskChars = null;
@@ -67,6 +70,7 @@ public class PinEntryEditText extends AppCompatEditText {
protected Drawable mPinBackground;
protected Rect mTextHeight = new Rect();
protected boolean mIsDigitSquare = false;
+ protected boolean mShouldSkipMaskLastChar = false;
protected OnClickListener mClickListener;
protected OnPinEnteredListener mOnPinEnteredListener = null;
@@ -76,6 +80,7 @@ public class PinEntryEditText extends AppCompatEditText {
protected Paint mLinesPaint;
protected boolean mAnimate = false;
protected boolean mHasError = false;
+ protected boolean mHideLastChar = false;
protected ColorStateList mOriginalTextColors;
protected int[][] mStates = new int[][]{
new int[]{android.R.attr.state_selected}, // selected
@@ -92,6 +97,7 @@ public class PinEntryEditText extends AppCompatEditText {
};
protected ColorStateList mColorStates = new ColorStateList(mStates, mColors);
+ private Handler mLastCharTimer = new Handler(Looper.getMainLooper());
public PinEntryEditText(Context context) {
super(context);
@@ -148,6 +154,7 @@ private void init(Context context, AttributeSet attrs) {
mTextBottomPadding = ta.getDimension(R.styleable.PinEntryEditText_pinTextBottomPadding, mTextBottomPadding);
mIsDigitSquare = ta.getBoolean(R.styleable.PinEntryEditText_pinBackgroundIsSquare, mIsDigitSquare);
mPinBackground = ta.getDrawable(R.styleable.PinEntryEditText_pinBackgroundDrawable);
+ mShouldSkipMaskLastChar = ta.getBoolean(R.styleable.PinEntryEditText_pinSkipMaskLastChar, mShouldSkipMaskLastChar);
ColorStateList colors = ta.getColorStateList(R.styleable.PinEntryEditText_pinLineColors);
if (colors != null) {
mColorStates = colors;
@@ -399,17 +406,29 @@ private StringBuilder getMaskChars() {
if (mMaskChars == null) {
mMaskChars = new StringBuilder();
}
- int textLength = getText().length();
- while (mMaskChars.length() != textLength) {
- if (mMaskChars.length() < textLength) {
- mMaskChars.append(mMask);
+ String text = getText().toString();
+ mMaskChars.delete(0, mMaskChars.length());
+ for (int i = 0; i < text.length(); i++) {
+ if (mShouldSkipMaskLastChar && !mHideLastChar && isFocused() && i == text.length() - 1) {
+ mMaskChars.append(text.charAt(i));
} else {
- mMaskChars.deleteCharAt(mMaskChars.length() - 1);
+ mMaskChars.append(mMask);
}
}
return mMaskChars;
}
+ private void startLastCharTimerIfNeeded() {
+ if (!mShouldSkipMaskLastChar) return;
+ mLastCharTimer.removeCallbacksAndMessages(null);
+ mLastCharTimer.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mHideLastChar = true;
+ if (mShouldSkipMaskLastChar) invalidate();
+ }
+ }, HIDE_LAST_CHAR_MILLIS);
+ }
private int getColorForState(int... states) {
return mColorStates.getColorForState(states, Color.GRAY);
@@ -508,15 +527,18 @@ public void setPinBackground(Drawable pinBackground) {
@Override
protected void onTextChanged(CharSequence text, final int start, int lengthBefore, final int lengthAfter) {
setError(false);
+ mHideLastChar = lengthAfter < lengthBefore;
if (mLineCoords == null || !mAnimate) {
if (mOnPinEnteredListener != null && text.length() == mMaxLength) {
mOnPinEnteredListener.onPinEntered(text);
}
+ startLastCharTimerIfNeeded();
return;
}
if (mAnimatedType == -1) {
invalidate();
+ startLastCharTimerIfNeeded();
return;
}
@@ -540,32 +562,34 @@ public void onAnimationUpdate(ValueAnimator animation) {
PinEntryEditText.this.invalidate();
}
});
- if (getText().length() == mMaxLength && mOnPinEnteredListener != null) {
- va.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
+ va.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (getText().length() == mMaxLength && mOnPinEnteredListener != null) {
mOnPinEnteredListener.onPinEntered(getText());
}
+ startLastCharTimerIfNeeded();
+ }
- @Override
- public void onAnimationCancel(Animator animation) {
- }
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+ });
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- });
- }
va.start();
}
- private void animateBottomUp(CharSequence text, final int start) {
+ private void animateBottomUp(final CharSequence text, final int start) {
mCharBottom[start] = mLineCoords[start].bottom - mTextBottomPadding;
- ValueAnimator animUp = ValueAnimator.ofFloat(mCharBottom[start] + getPaint().getTextSize(), mCharBottom[start]);
+ final ValueAnimator animUp = ValueAnimator.ofFloat(mCharBottom[start] + getPaint().getTextSize(), mCharBottom[start]);
animUp.setDuration(300);
animUp.setInterpolator(new OvershootInterpolator());
animUp.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -578,7 +602,7 @@ public void onAnimationUpdate(ValueAnimator animation) {
});
mLastCharPaint.setAlpha(255);
- ValueAnimator animAlpha = ValueAnimator.ofInt(0, 255);
+ final ValueAnimator animAlpha = ValueAnimator.ofInt(0, 255);
animAlpha.setDuration(300);
animAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -588,29 +612,30 @@ public void onAnimationUpdate(ValueAnimator animation) {
}
});
- AnimatorSet set = new AnimatorSet();
- if (text.length() == mMaxLength && mOnPinEnteredListener != null) {
- set.addListener(new Animator.AnimatorListener() {
+ final AnimatorSet set = new AnimatorSet();
+ set.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (text.length() == mMaxLength && mOnPinEnteredListener != null) {
mOnPinEnteredListener.onPinEntered(getText());
}
+ startLastCharTimerIfNeeded();
+ }
- @Override
- public void onAnimationCancel(Animator animation) {
- }
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
- @Override
- public void onAnimationRepeat(Animator animation) {
+ @Override
+ public void onAnimationRepeat(Animator animation) {
- }
- });
- }
+ }
+ });
set.playTogether(animUp, animAlpha);
set.start();
}
diff --git a/pinentryedittext/src/main/res/values/attrs.xml b/pinentryedittext/src/main/res/values/attrs.xml
index 848abdb..2020f9d 100755
--- a/pinentryedittext/src/main/res/values/attrs.xml
+++ b/pinentryedittext/src/main/res/values/attrs.xml
@@ -15,5 +15,6 @@
+
\ No newline at end of file
diff --git a/sample-app/src/main/res/layout/activity_edit_text.xml b/sample-app/src/main/res/layout/activity_edit_text.xml
index b725766..635d1a4 100755
--- a/sample-app/src/main/res/layout/activity_edit_text.xml
+++ b/sample-app/src/main/res/layout/activity_edit_text.xml
@@ -43,7 +43,7 @@
android:background="@null"
android:cursorVisible="false"
android:digits="1234567890"
- android:inputType="number"
+ android:inputType="numberPassword"
android:maxLength="6"
android:textIsSelectable="false"
android:textSize="24dp"
@@ -51,6 +51,7 @@
app:pinBackgroundDrawable="@drawable/bg_pin"
app:pinBackgroundIsSquare="true"
app:pinCharacterSpacing="4dp"
+ app:pinSkipMaskLastChar="true"
app:pinTextBottomPadding="16dp"
tools:ignore="SpUsage" />