44 * Created by Swapnil Tiwari on 2019-05-07.
5566 */
7+
78import android .content .Context ;
89import android .content .res .TypedArray ;
910import android .graphics .Canvas ;
1011import android .graphics .Paint ;
1112
13+ import androidx .annotation .ColorRes ;
1214import androidx .annotation .Nullable ;
1315import androidx .core .content .ContextCompat ;
1416import androidx .appcompat .widget .AppCompatEditText ;
17+
1518import android .text .Editable ;
1619import android .text .TextWatcher ;
1720import android .util .AttributeSet ;
@@ -29,6 +32,7 @@ public class OtpEditText extends AppCompatEditText implements TextWatcher {
2932 private Paint mLinesPaint ;
3033 private Paint mStrokePaint ;
3134 private Paint mTextPaint ;
35+ private Paint mHintPaint ;
3236
3337 private boolean mMaskInput ;
3438
@@ -37,6 +41,7 @@ public class OtpEditText extends AppCompatEditText implements TextWatcher {
3741 private int mPrimaryColor ;
3842 private int mSecondaryColor ;
3943 private int mTextColor ;
44+ private int mHintTextColor ;
4045
4146 private float mLineStrokeSelected = 2 ; //2dp by default
4247 private float mLineStroke = 1 ; //1dp by default
@@ -47,12 +52,16 @@ public class OtpEditText extends AppCompatEditText implements TextWatcher {
4752
4853 private String mBoxStyle ;
4954 private String mMaskCharacter = "*" ;
55+ private String mHintText = "" ;
5056
5157 private final String ROUNDED_BOX = "rounded_box" ;
5258 private final String UNDERLINE = "underline" ;
5359 private final String SQUARE_BOX = "square_box" ;
5460 private final String ROUNDED_UNDERLINE = "rounded_underline" ;
5561
62+ float [] textWidths ;
63+ float [] hintWidth = new float [1 ];
64+
5665 private OnCompleteListener completeListener ;
5766
5867 public OtpEditText (Context context ) {
@@ -79,6 +88,9 @@ private void init(Context context, @Nullable AttributeSet attrs) {
7988 mTextPaint = getPaint ();
8089 mTextPaint .setColor (mTextColor );
8190
91+ mHintPaint = new Paint (getPaint ());
92+ mHintPaint .setColor (mHintTextColor );
93+
8294 // Set the TextWatcher
8395 this .addTextChangedListener (this );
8496 float multi = context .getResources ().getDisplayMetrics ().density ;
@@ -126,6 +138,8 @@ private void getAttrsFromTypedArray(AttributeSet attributeSet) {
126138 final TypedArray a = getContext ().obtainStyledAttributes (attributeSet , R .styleable .OtpEditText , defStyleAttr , 0 );
127139
128140 mMaxLength = attributeSet .getAttributeIntValue (XML_NAMESPACE_ANDROID , "maxLength" , 6 );
141+ mHintText = attributeSet .getAttributeValue (XML_NAMESPACE_ANDROID , "hint" );
142+ mHintTextColor = attributeSet .getAttributeIntValue (XML_NAMESPACE_ANDROID , "textColorHint" , getResources ().getColor (R .color .hint_color ));
129143 mPrimaryColor = a .getColor (R .styleable .OtpEditText_oev_primary_color , getResources ().getColor (android .R .color .holo_red_dark ));
130144 mSecondaryColor = a .getColor (R .styleable .OtpEditText_oev_secondary_color , getResources ().getColor (R .color .light_gray ));
131145 mTextColor = a .getColor (R .styleable .OtpEditText_oev_text_color , getResources ().getColor (android .R .color .black ));
@@ -174,13 +188,17 @@ private void getAttrsFromTypedArray(AttributeSet attributeSet) {
174188 @ Nullable
175189 public String getOtpValue () {
176190 if (String .valueOf (getText ()).length () != mMaxLength ) {
177- this . startAnimation ( AnimationUtils . loadAnimation ( getContext (), R . anim . shake ) );
191+ triggerErrorAnimation ( );
178192 return null ;
179193 } else {
180194 return String .valueOf (getText ());
181195 }
182196 }
183197
198+ public void triggerErrorAnimation () {
199+ this .startAnimation (AnimationUtils .loadAnimation (getContext (), R .anim .shake ));
200+ }
201+
184202 @ Override
185203 public void setCustomSelectionActionModeCallback (ActionMode .Callback actionModeCallback ) {
186204 throw new RuntimeException ("setCustomSelectionActionModeCallback() not supported." );
@@ -198,13 +216,32 @@ protected void onDraw(Canvas canvas) {
198216 mLineSpacing = (float ) (getHeight () * .6 );
199217
200218 int startX = getPaddingLeft ();
219+ int hintStartX = getPaddingLeft ();
201220 int bottom = getHeight () - getPaddingBottom ();
202221 int top = getPaddingTop ();
203222
204223 //Text Width
205224 Editable text = getText ();
225+
226+
206227 int textLength = text .length ();
207- float [] textWidths = new float [textLength ];
228+ textWidths = new float [textLength ];
229+
230+
231+ if (text .length () == 0 && !mHintText .isEmpty ()) {
232+ getPaint ().getTextWidths ("1" , 0 , 1 , hintWidth );
233+ for (int i = 0 ; i < mNumChars && i < mHintText .length (); i ++) {
234+ float middle = hintStartX + mCharSize / 2 ;
235+ canvas .drawText (mHintText , i , i + 1 , middle - hintWidth [0 ] / 2 , mLineSpacing , mHintPaint );
236+
237+ if (mSpace < 0 ) {
238+ hintStartX += mCharSize * 2 ;
239+ } else {
240+ hintStartX += mCharSize + mSpace ;
241+ }
242+ }
243+ }
244+
208245 getPaint ().getTextWidths (getText (), 0 , textLength , textWidths );
209246
210247 for (int i = 0 ; i < mNumChars ; i ++) {
@@ -240,9 +277,9 @@ protected void onDraw(Canvas canvas) {
240277 if (getText ().length () > i ) {
241278 float middle = startX + mCharSize / 2 ;
242279 if (mMaskInput ) {
243- canvas .drawText (getMaskText (), i , i + 1 , middle - textWidths [0 ] / 2 , mLineSpacing , getPaint () );
280+ canvas .drawText (getMaskText (), i , i + 1 , middle - textWidths [0 ] / 2 , mLineSpacing , mTextPaint );
244281 } else {
245- canvas .drawText (text , i , i + 1 , middle - textWidths [0 ] / 2 , mLineSpacing , getPaint () );
282+ canvas .drawText (text , i , i + 1 , middle - textWidths [0 ] / 2 , mLineSpacing , mTextPaint );
246283 }
247284 }
248285
@@ -251,6 +288,7 @@ protected void onDraw(Canvas canvas) {
251288 } else {
252289 startX += mCharSize + mSpace ;
253290 }
291+
254292 }
255293 }
256294
0 commit comments