28
28
import android .graphics .PointF ;
29
29
import android .graphics .Rect ;
30
30
import android .graphics .RectF ;
31
+ import android .graphics .Typeface ;
32
+ import android .graphics .drawable .ColorDrawable ;
33
+ import android .graphics .drawable .Drawable ;
31
34
import android .support .annotation .ColorInt ;
35
+ import android .support .annotation .DrawableRes ;
32
36
import android .support .annotation .Nullable ;
33
37
import android .support .annotation .Px ;
38
+ import android .support .v4 .content .res .ResourcesCompat ;
34
39
import android .support .v4 .view .ViewCompat ;
35
40
import android .support .v7 .widget .AppCompatEditText ;
36
41
import android .text .InputFilter ;
@@ -60,8 +65,12 @@ public class PinView extends AppCompatEditText {
60
65
61
66
private static final InputFilter [] NO_FILTERS = new InputFilter [0 ];
62
67
68
+ private static final int [] HIGHLIGHT_STATES = new int []{
69
+ android .R .attr .state_selected };
70
+
63
71
private static final int VIEW_TYPE_RECTANGLE = 0 ;
64
72
private static final int VIEW_TYPE_LINE = 1 ;
73
+ private static final int VIEW_TYPE_NONE = 2 ;
65
74
66
75
private int mViewType ;
67
76
@@ -73,8 +82,7 @@ public class PinView extends AppCompatEditText {
73
82
private int mPinItemSpacing ;
74
83
75
84
private final Paint mPaint ;
76
- private final TextPaint mTextPaint ;
77
- private final Paint mAnimatorTextPaint ;
85
+ private final TextPaint mAnimatorTextPaint = new TextPaint ();
78
86
79
87
private ColorStateList mLineColor ;
80
88
private int mCurLineColor = Color .BLACK ;
@@ -96,6 +104,9 @@ public class PinView extends AppCompatEditText {
96
104
private int mCursorWidth ;
97
105
private int mCursorColor ;
98
106
107
+ private int mItemBackgroundResource ;
108
+ private Drawable mItemBackground ;
109
+
99
110
public PinView (Context context ) {
100
111
this (context , null );
101
112
}
@@ -112,12 +123,7 @@ public PinView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
112
123
mPaint = new Paint (Paint .ANTI_ALIAS_FLAG );
113
124
mPaint .setStyle (Paint .Style .STROKE );
114
125
115
- mTextPaint = new TextPaint (Paint .ANTI_ALIAS_FLAG );
116
- mTextPaint .density = res .getDisplayMetrics ().density ;
117
- mTextPaint .setStyle (Paint .Style .FILL );
118
- mTextPaint .setTextSize (getTextSize ());
119
-
120
- mAnimatorTextPaint = new TextPaint (mTextPaint );
126
+ mAnimatorTextPaint .set (getPaint ());
121
127
122
128
final Resources .Theme theme = context .getTheme ();
123
129
@@ -140,6 +146,8 @@ public PinView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
140
146
mCursorWidth = a .getDimensionPixelSize (R .styleable .PinView_cursorWidth ,
141
147
res .getDimensionPixelSize (R .dimen .pv_pin_view_cursor_width ));
142
148
149
+ mItemBackground = a .getDrawable (R .styleable .PinView_itemBackground );
150
+
143
151
a .recycle ();
144
152
145
153
if (mLineColor != null ) {
@@ -157,6 +165,19 @@ public PinView(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
157
165
setTextIsSelectable (false );
158
166
}
159
167
168
+ @ Override
169
+ public void setTypeface (Typeface tf , int style ) {
170
+ super .setTypeface (tf , style );
171
+ }
172
+
173
+ @ Override
174
+ public void setTypeface (Typeface tf ) {
175
+ super .setTypeface (tf );
176
+ if (mAnimatorTextPaint != null ) {
177
+ mAnimatorTextPaint .set (getPaint ());
178
+ }
179
+ }
180
+
160
181
private void setMaxLength (int maxLength ) {
161
182
if (maxLength >= 0 ) {
162
183
setFilters (new InputFilter []{new InputFilter .LengthFilter (maxLength )});
@@ -187,10 +208,11 @@ private void checkItemRadius() {
187
208
if (mPinItemRadius > halfOfLineWidth ) {
188
209
throw new IllegalArgumentException ("The itemRadius can not be greater than lineWidth when viewType is line" );
189
210
}
190
- }
191
- float halfOfItemWidth = ((float ) mPinItemWidth ) / 2 ;
192
- if (mPinItemRadius > halfOfItemWidth ) {
193
- throw new IllegalArgumentException ("The itemRadius can not be greater than itemWidth" );
211
+ } else if (mViewType == VIEW_TYPE_RECTANGLE ) {
212
+ float halfOfItemWidth = ((float ) mPinItemWidth ) / 2 ;
213
+ if (mPinItemRadius > halfOfItemWidth ) {
214
+ throw new IllegalArgumentException ("The itemRadius can not be greater than itemWidth" );
215
+ }
194
216
}
195
217
}
196
218
@@ -292,17 +314,25 @@ private void updatePaints() {
292
314
mPaint .setColor (mCurLineColor );
293
315
mPaint .setStyle (Paint .Style .STROKE );
294
316
mPaint .setStrokeWidth (mLineWidth );
295
- mTextPaint .setColor (getCurrentTextColor ());
317
+ getPaint () .setColor (getCurrentTextColor ());
296
318
}
297
319
298
320
private void drawPinView (Canvas canvas ) {
299
321
for (int i = 0 ; i < mPinItemCount ; i ++) {
300
322
updateItemRectF (i );
301
323
updateCenterPoint ();
302
324
325
+ canvas .save ();
326
+ if (mViewType == VIEW_TYPE_RECTANGLE ) {
327
+ updatePinBoxPath (i );
328
+ canvas .clipPath (mPath );
329
+ }
330
+ drawItemBackground (canvas , false );
331
+ canvas .restore ();
332
+
303
333
if (mViewType == VIEW_TYPE_RECTANGLE ) {
304
334
drawPinBox (canvas , i );
305
- } else {
335
+ } else if ( mViewType == VIEW_TYPE_LINE ) {
306
336
drawPinLine (canvas , i );
307
337
}
308
338
@@ -327,13 +357,21 @@ private void drawPinView(Canvas canvas) {
327
357
updateItemRectF (index );
328
358
updateCenterPoint ();
329
359
330
- mPaint .setColor (getLineColorForState (android .R .attr .state_selected ));
360
+ canvas .save ();
361
+ if (mViewType == VIEW_TYPE_RECTANGLE ) {
362
+ updatePinBoxPath (index );
363
+ canvas .clipPath (mPath );
364
+ }
365
+ drawItemBackground (canvas , true );
366
+ canvas .restore ();
367
+
368
+ mPaint .setColor (getLineColorForState (HIGHLIGHT_STATES ));
331
369
332
370
drawCursor (canvas );
333
371
334
372
if (mViewType == VIEW_TYPE_RECTANGLE ) {
335
373
drawPinBox (canvas , index );
336
- } else {
374
+ } else if ( mViewType == VIEW_TYPE_LINE ) {
337
375
drawPinLine (canvas , index );
338
376
}
339
377
}
@@ -343,7 +381,22 @@ private int getLineColorForState(int... states) {
343
381
return mLineColor != null ? mLineColor .getColorForState (states , mCurLineColor ) : mCurLineColor ;
344
382
}
345
383
346
- private void drawPinBox (Canvas canvas , int i ) {
384
+ private void drawItemBackground (Canvas canvas , boolean highlight ) {
385
+ if (mItemBackground == null ) {
386
+ return ;
387
+ }
388
+ float delta = (float ) mLineWidth / 2 ;
389
+ int left = Math .round (mItemBorderRect .left - delta );
390
+ int top = Math .round (mItemBorderRect .top - delta );
391
+ int right = Math .round (mItemBorderRect .right + delta );
392
+ int bottom = Math .round (mItemBorderRect .bottom + delta );
393
+
394
+ mItemBackground .setBounds (left , top , right , bottom );
395
+ mItemBackground .setState (highlight ? HIGHLIGHT_STATES : getDrawableState ());
396
+ mItemBackground .draw (canvas );
397
+ }
398
+
399
+ private void updatePinBoxPath (int i ) {
347
400
boolean drawRightCorner = false ;
348
401
boolean drawLeftCorner = false ;
349
402
if (mPinItemSpacing != 0 ) {
@@ -357,6 +410,10 @@ private void drawPinBox(Canvas canvas, int i) {
357
410
}
358
411
}
359
412
updateRoundRectPath (mItemBorderRect , mPinItemRadius , mPinItemRadius , drawLeftCorner , drawRightCorner );
413
+ }
414
+
415
+ private void drawPinBox (Canvas canvas , int i ) {
416
+ // updatePinBoxPath(canvas, i);
360
417
canvas .drawPath (mPath , mPaint );
361
418
}
362
419
@@ -378,7 +435,11 @@ private void drawPinLine(Canvas canvas, int i) {
378
435
mPaint .setStyle (Paint .Style .FILL );
379
436
mPaint .setStrokeWidth (((float ) mLineWidth ) / 10 );
380
437
float halfLineWidth = ((float ) mLineWidth ) / 2 ;
381
- mItemLineRect .set (mItemBorderRect .left , mItemBorderRect .bottom - halfLineWidth , mItemBorderRect .right , mItemBorderRect .bottom + halfLineWidth );
438
+ mItemLineRect .set (
439
+ mItemBorderRect .left - halfLineWidth ,
440
+ mItemBorderRect .bottom - halfLineWidth ,
441
+ mItemBorderRect .right + halfLineWidth ,
442
+ mItemBorderRect .bottom + halfLineWidth );
382
443
383
444
updateRoundRectPath (mItemLineRect , mPinItemRadius , mPinItemRadius , l , r );
384
445
canvas .drawPath (mPath , mPaint );
@@ -511,10 +572,10 @@ private void drawCircle(Canvas canvas, int i) {
511
572
512
573
private Paint getPaintByIndex (int i ) {
513
574
if (isAnimationEnable && i == getText ().length () - 1 ) {
514
- mAnimatorTextPaint .setColor (mTextPaint .getColor ());
575
+ mAnimatorTextPaint .setColor (getPaint () .getColor ());
515
576
return mAnimatorTextPaint ;
516
577
} else {
517
- return mTextPaint ;
578
+ return getPaint () ;
518
579
}
519
580
}
520
581
@@ -780,7 +841,7 @@ public void setTextSize(int unit, float size) {
780
841
updateCursorHeight ();
781
842
}
782
843
783
- //region Cursor
844
+ //region Cursorint
784
845
785
846
/**
786
847
* Sets the width (in pixels) of cursor.
@@ -829,6 +890,48 @@ public int getCursorColor() {
829
890
return mCursorColor ;
830
891
}
831
892
893
+ /**
894
+ * Set the item background to a given resource. The resource should refer to
895
+ * a Drawable object or 0 to remove the item background.
896
+ *
897
+ * @param resId The identifier of the resource.
898
+ * @attr ref R.styleable#PinView_itemBackground
899
+ */
900
+ public void setItemBackgroundResources (@ DrawableRes int resId ) {
901
+ if (resId != 0 && mItemBackgroundResource != resId ) {
902
+ return ;
903
+ }
904
+ mItemBackground = ResourcesCompat .getDrawable (getResources (), resId , getContext ().getTheme ());
905
+ setItemBackground (mItemBackground );
906
+ mItemBackgroundResource = resId ;
907
+ }
908
+
909
+ /**
910
+ * Sets the item background color for this view.
911
+ *
912
+ * @param color the color of the item background
913
+ */
914
+ public void setItemBackgroundColor (@ ColorInt int color ) {
915
+ if (mItemBackground instanceof ColorDrawable ) {
916
+ ((ColorDrawable ) mItemBackground .mutate ()).setColor (color );
917
+ mItemBackgroundResource = 0 ;
918
+ } else {
919
+ setItemBackground (new ColorDrawable (color ));
920
+ }
921
+ }
922
+
923
+ /**
924
+ * Set the item background to a given Drawable, or remove the background.
925
+ *
926
+ * @param background The Drawable to use as the item background, or null to remove the
927
+ * item background
928
+ */
929
+ public void setItemBackground (Drawable background ) {
930
+ mItemBackgroundResource = 0 ;
931
+ mItemBackground = background ;
932
+ invalidate ();
933
+ }
934
+
832
935
@ Override
833
936
public void setCursorVisible (boolean visible ) {
834
937
if (isCursorVisible != visible ) {
0 commit comments