20 | * Created by aritraroy on 01/06/16.
21 | */
22 | public class IndicatorDots extends LinearLayout {
23 |
24 | @IntDef({IndicatorType.FIXED, IndicatorType.FILL, IndicatorType.FILL_WITH_ANIMATION})
25 | @Retention(RetentionPolicy.SOURCE)
26 | public @interface IndicatorType {
27 | int FIXED = 0;
28 | int FILL = 1;
29 | int FILL_WITH_ANIMATION = 2;
30 | }
31 |
32 | private static final int DEFAULT_PIN_LENGTH = 4;
33 |
34 | private int mDotDiameter;
35 | private int mDotSpacing;
36 | private int mFillDrawable;
37 | private int mEmptyDrawable;
38 | private int mPinLength;
39 | private int mIndicatorType;
40 |
41 | private int mPreviousLength;
42 |
43 | public IndicatorDots(Context context) {
44 | this(context, null);
45 | }
46 |
47 | public IndicatorDots(Context context, AttributeSet attrs) {
48 | this(context, attrs, 0);
49 | }
50 |
51 | public IndicatorDots(Context context, AttributeSet attrs, int defStyleAttr) {
52 | super(context, attrs, defStyleAttr);
53 |
54 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PinLockView);
55 |
56 | try {
57 | mDotDiameter = (int) typedArray.getDimension(R.styleable.PinLockView_dotDiameter, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_diameter));
58 | mDotSpacing = (int) typedArray.getDimension(R.styleable.PinLockView_dotSpacing, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_spacing));
59 | mFillDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotFilledBackground,
60 | R.drawable.dot_filled);
61 | mEmptyDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotEmptyBackground,
62 | R.drawable.dot_empty);
63 | mPinLength = typedArray.getInt(R.styleable.PinLockView_pinLength, DEFAULT_PIN_LENGTH);
64 | mIndicatorType = typedArray.getInt(R.styleable.PinLockView_indicatorType,
65 | IndicatorType.FIXED);
66 | } finally {
67 | typedArray.recycle();
68 | }
69 |
70 | initView(context);
71 | }
72 |
73 | private void initView(Context context) {
74 | ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR);
75 | if (mIndicatorType == 0) {
76 | for (int i = 0; i < mPinLength; i++) {
77 | View dot = new View(context);
78 | emptyDot(dot);
79 |
80 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mDotDiameter,
81 | mDotDiameter);
82 | params.setMargins(mDotSpacing, 0, mDotSpacing, 0);
83 | dot.setLayoutParams(params);
84 |
85 | addView(dot);
86 | }
87 | } else if (mIndicatorType == 2) {
88 | setLayoutTransition(new LayoutTransition());
89 | }
90 | }
91 |
92 | @Override
93 | protected void onAttachedToWindow() {
94 | super.onAttachedToWindow();
95 | // If the indicator type is not fixed
96 | if (mIndicatorType != 0) {
97 | ViewGroup.LayoutParams params = this.getLayoutParams();
98 | params.height = mDotDiameter;
99 | requestLayout();
100 | }
101 | }
102 |
103 | void updateDot(int length) {
104 | if (mIndicatorType == 0) {
105 | if (length > 0) {
106 | if (length > mPreviousLength) {
107 | fillDot(getChildAt(length - 1));
108 | } else {
109 | emptyDot(getChildAt(length));
110 | }
111 | mPreviousLength = length;
112 | } else {
113 | // When {@code mPinLength} is 0, we need to reset all the views back to empty
114 | for (int i = 0; i < getChildCount(); i++) {
115 | View v = getChildAt(i);
116 | emptyDot(v);
117 | }
118 | mPreviousLength = 0;
119 | }
120 | } else {
121 | if (length > 0) {
122 | if (length > mPreviousLength) {
123 | View dot = new View(getContext());
124 | fillDot(dot);
125 |
126 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mDotDiameter,
127 | mDotDiameter);
128 | params.setMargins(mDotSpacing, 0, mDotSpacing, 0);
129 | dot.setLayoutParams(params);
130 |
131 | addView(dot, length - 1);
132 | } else {
133 | removeViewAt(length);
134 | }
135 | mPreviousLength = length;
136 | } else {
137 | removeAllViews();
138 | mPreviousLength = 0;
139 | }
140 | }
141 | }
142 |
143 | private void emptyDot(View dot) {
144 | dot.setBackgroundResource(mEmptyDrawable);
145 | }
146 |
147 | private void fillDot(View dot) {
148 | dot.setBackgroundResource(mFillDrawable);
149 | }
150 |
151 | public int getPinLength() {
152 | return mPinLength;
153 | }
154 |
155 | public void setPinLength(int pinLength) {
156 | this.mPinLength = pinLength;
157 | removeAllViews();
158 | initView(getContext());
159 | }
160 |
161 | public
162 | @IndicatorType
163 | int getIndicatorType() {
164 | return mIndicatorType;
165 | }
166 |
167 | public void setIndicatorType(@IndicatorType int type) {
168 | this.mIndicatorType = type;
169 | removeAllViews();
170 | initView(getContext());
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.java:
--------------------------------------------------------------------------------
1 | package com.andrognito.pinlockview;
2 |
3 | import android.graphics.Rect;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 |
7 | /**
8 | * Created by aritraroy on 31/05/16.
9 | */
10 | public class ItemSpaceDecoration extends RecyclerView.ItemDecoration {
11 |
12 | private final int mHorizontalSpaceWidth;
13 | private final int mVerticalSpaceHeight;
14 | private final int mSpanCount;
15 | private final boolean mIncludeEdge;
16 |
17 | public ItemSpaceDecoration(int horizontalSpaceWidth, int verticalSpaceHeight, int spanCount, boolean includeEdge) {
18 | this.mHorizontalSpaceWidth = horizontalSpaceWidth;
19 | this.mVerticalSpaceHeight = verticalSpaceHeight;
20 | this.mSpanCount = spanCount;
21 | this.mIncludeEdge = includeEdge;
22 | }
23 |
24 | @Override
25 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
26 |
27 | int position = parent.getChildAdapterPosition(view);
28 | int column = position % mSpanCount;
29 |
30 | if (mIncludeEdge) {
31 | outRect.left = mHorizontalSpaceWidth - column * mHorizontalSpaceWidth / mSpanCount;
32 | outRect.right = (column + 1) * mHorizontalSpaceWidth / mSpanCount;
33 |
34 | if (position < mSpanCount) {
35 | outRect.top = mVerticalSpaceHeight;
36 | }
37 | outRect.bottom = mVerticalSpaceHeight;
38 | } else {
39 | outRect.left = column * mHorizontalSpaceWidth / mSpanCount;
40 | outRect.right = mHorizontalSpaceWidth - (column + 1) * mHorizontalSpaceWidth / mSpanCount;
41 | if (position >= mSpanCount) {
42 | outRect.top = mVerticalSpaceHeight;
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.andrognito.pinlockview;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.GridLayoutManager;
5 | import android.util.AttributeSet;
6 |
7 | /**
8 | * Used to always maintain an LTR layout no matter what is the real device's layout direction
9 | * to avoid an unwanted reversed direction in RTL devices
10 | * Created by Idan on 7/6/2017.
11 | */
12 |
13 | public class LTRGridLayoutManager extends GridLayoutManager {
14 |
15 | public LTRGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
16 | super(context, attrs, defStyleAttr, defStyleRes);
17 | }
18 |
19 | public LTRGridLayoutManager(Context context, int spanCount) {
20 | super(context, spanCount);
21 | }
22 |
23 | public LTRGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
24 | super(context, spanCount, orientation, reverseLayout);
25 | }
26 |
27 | @Override
28 | protected boolean isLayoutRTL(){
29 | return false;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.java:
--------------------------------------------------------------------------------
1 | package com.andrognito.pinlockview;
2 |
3 | import android.content.Context;
4 | import android.graphics.PorterDuff;
5 | import android.graphics.Rect;
6 | import android.os.Build;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.util.TypedValue;
9 | import android.view.LayoutInflater;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.Button;
14 | import android.widget.ImageView;
15 | import android.widget.LinearLayout;
16 |
17 | /**
18 | * Created by aritraroy on 31/05/16.
19 | */
20 | public class PinLockAdapter extends RecyclerView.Adapter