diff --git a/app/build.gradle b/app/build.gradle
index de9556a1..d0b0db20 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,13 +1,14 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-android'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.3"
+ compileSdkVersion 28
defaultConfig {
applicationId "com.andrognito.pinlockviewapp"
- minSdkVersion 11
- targetSdkVersion 25
+ minSdkVersion 16
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
}
@@ -19,9 +20,23 @@ android {
}
}
+allprojects {
+ gradle.projectsEvaluated {
+ tasks.withType(JavaCompile) {
+ options.compilerArgs << "-Xlint:deprecation"
+ }
+ }
+}
+
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:25.3.1'
- compile project(':pinlockview')
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':pinlockview')
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.recyclerview:recyclerview:1.0.0'
+ testImplementation 'junit:junit:4.12'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "androidx.core:core-ktx:1.0.1"
+}
+repositories {
+ mavenCentral()
}
diff --git a/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.java b/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.java
deleted file mode 100644
index f6414d5a..00000000
--- a/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.andrognito.pinlockviewapp;
-
-import android.os.Bundle;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.Window;
-import android.view.WindowManager;
-
-import com.andrognito.pinlockview.IndicatorDots;
-import com.andrognito.pinlockview.PinLockListener;
-import com.andrognito.pinlockview.PinLockView;
-
-public class SampleActivity extends AppCompatActivity {
-
- public static final String TAG = "PinLockView";
-
- private PinLockView mPinLockView;
- private IndicatorDots mIndicatorDots;
-
- private PinLockListener mPinLockListener = new PinLockListener() {
- @Override
- public void onComplete(String pin) {
- Log.d(TAG, "Pin complete: " + pin);
- }
-
- @Override
- public void onEmpty() {
- Log.d(TAG, "Pin empty");
- }
-
- @Override
- public void onPinChange(int pinLength, String intermediatePin) {
- Log.d(TAG, "Pin changed, new length " + pinLength + " with intermediate pin " + intermediatePin);
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- setContentView(R.layout.activity_sample);
-
- mPinLockView = (PinLockView) findViewById(R.id.pin_lock_view);
- mIndicatorDots = (IndicatorDots) findViewById(R.id.indicator_dots);
-
- mPinLockView.attachIndicatorDots(mIndicatorDots);
- mPinLockView.setPinLockListener(mPinLockListener);
- //mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4});
- //mPinLockView.enableLayoutShuffling();
-
- mPinLockView.setPinLength(4);
- mPinLockView.setTextColor(ContextCompat.getColor(this, R.color.white));
-
- mIndicatorDots.setIndicatorType(IndicatorDots.IndicatorType.FILL_WITH_ANIMATION);
- }
-}
diff --git a/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.kt b/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.kt
new file mode 100644
index 00000000..3de7ce69
--- /dev/null
+++ b/app/src/main/java/com/andrognito/pinlockviewapp/SampleActivity.kt
@@ -0,0 +1,103 @@
+package com.andrognito.pinlockviewapp
+
+import android.os.Bundle
+import android.os.Handler
+import android.util.Log
+import android.view.Window
+import android.view.WindowManager
+import android.view.animation.AnimationUtils
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import com.andrognito.pinlockview.IndicatorDots
+import com.andrognito.pinlockview.PinLockListener
+import com.andrognito.pinlockview.PinLockView
+
+class SampleActivity : AppCompatActivity() {
+
+ private var mPinLockView: PinLockView? = null
+ private var mIndicatorDotsFirst: IndicatorDots? = null
+ private var mIndicatorDotsSecond: IndicatorDots? = null
+
+ private val mPinLockFirstListener = object : PinLockListener {
+ override fun onComplete(pin: String) {
+ Log.d(TAG, "Pin complete: $pin")
+ val shake = AnimationUtils.loadAnimation(this@SampleActivity, R.anim.shake_wrong)
+ if (pin == "1111") {
+ mIndicatorDotsFirst!!.setSuccessDots()
+ } else {
+ mIndicatorDotsFirst!!.setErrorDots()
+ mIndicatorDotsFirst!!.startAnimation(shake)
+ }
+ Handler().postDelayed({
+ mIndicatorDotsFirst!!.setDefaultDots()
+ mPinLockView!!.resetPinLockView()
+
+ // mPinLockView.attachIndicatorDots(mIndicatorDotsSecond);
+ }, 1000)
+ }
+
+ override fun onEmpty() {
+ Log.d(TAG, "Pin empty")
+ }
+
+ override fun onPinChange(pinLength: Int, intermediatePin: String) {
+ Log.d(TAG, "Pin changed, new length $pinLength with intermediate pin $intermediatePin")
+ }
+ }
+
+ private val mPinLockSecondListener = object : PinLockListener {
+ override fun onComplete(pin: String) {
+ Log.d(TAG, "Pin complete: $pin")
+ val shake = AnimationUtils.loadAnimation(this@SampleActivity, R.anim.shake_wrong)
+ mIndicatorDotsFirst!!.startAnimation(shake)
+ // mIndicatorDotsFirst.setErrorDots();
+ if (pin == "1111") {
+ mIndicatorDotsFirst!!.setSuccessDots()
+ } else {
+ mIndicatorDotsFirst!!.setErrorDots()
+ }
+ Handler().postDelayed({
+ mIndicatorDotsFirst!!.setDefaultDots()
+ mPinLockView!!.resetPinLockView()
+
+ // mPinLockView.attachIndicatorDots(mIndicatorDotsSecond);
+ }, 1000)
+ }
+
+ override fun onEmpty() {
+ Log.d(TAG, "Pin empty")
+ }
+
+ override fun onPinChange(pinLength: Int, intermediatePin: String) {
+ Log.d(TAG, "Pin changed, new length $pinLength with intermediate pin $intermediatePin")
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ requestWindowFeature(Window.FEATURE_NO_TITLE)
+ window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN)
+ setContentView(R.layout.activity_sample)
+
+ mPinLockView = findViewById(R.id.pin_lock_view)
+ mIndicatorDotsFirst = findViewById(R.id.indicator_dots_first)
+ mIndicatorDotsSecond = findViewById(R.id.indicator_dots_second)
+
+
+ mPinLockView!!.attachIndicatorDots(mIndicatorDotsFirst!!)
+ mPinLockView!!.setPinLockListener(mPinLockFirstListener)
+ //mPinLockView.setCustomKeySet(new int[]{2, 3, 1, 5, 9, 6, 7, 0, 8, 4});
+ //mPinLockView.enableLayoutShuffling();
+
+ mPinLockView!!.pinLength = 4
+ mPinLockView!!.textColor = ContextCompat.getColor(this, R.color.white)
+
+ mIndicatorDotsFirst!!.indicatorType = IndicatorDots.IndicatorType.FIXED
+ }
+
+ companion object {
+
+ val TAG = "PinLockView"
+ }
+}
diff --git a/app/src/main/res/layout/activity_sample.xml b/app/src/main/res/layout/activity_sample.xml
index 05b65c72..f451c7da 100644
--- a/app/src/main/res/layout/activity_sample.xml
+++ b/app/src/main/res/layout/activity_sample.xml
@@ -7,21 +7,21 @@
android:background="@color/mine_shaft"
tools:context="com.andrognito.pinlockviewapp.SampleActivity">
-
-
+ android:layout_marginTop="32dp" />
+
+
- * Created by aritraroy on 01/06/16.
- */
-public class IndicatorDots extends LinearLayout {
-
- @IntDef({IndicatorType.FIXED, IndicatorType.FILL, IndicatorType.FILL_WITH_ANIMATION})
- @Retention(RetentionPolicy.SOURCE)
- public @interface IndicatorType {
- int FIXED = 0;
- int FILL = 1;
- int FILL_WITH_ANIMATION = 2;
- }
-
- private static final int DEFAULT_PIN_LENGTH = 4;
-
- private int mDotDiameter;
- private int mDotSpacing;
- private int mFillDrawable;
- private int mEmptyDrawable;
- private int mPinLength;
- private int mIndicatorType;
-
- private int mPreviousLength;
-
- public IndicatorDots(Context context) {
- this(context, null);
- }
-
- public IndicatorDots(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public IndicatorDots(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PinLockView);
-
- try {
- mDotDiameter = (int) typedArray.getDimension(R.styleable.PinLockView_dotDiameter, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_diameter));
- mDotSpacing = (int) typedArray.getDimension(R.styleable.PinLockView_dotSpacing, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_spacing));
- mFillDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotFilledBackground,
- R.drawable.dot_filled);
- mEmptyDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotEmptyBackground,
- R.drawable.dot_empty);
- mPinLength = typedArray.getInt(R.styleable.PinLockView_pinLength, DEFAULT_PIN_LENGTH);
- mIndicatorType = typedArray.getInt(R.styleable.PinLockView_indicatorType,
- IndicatorType.FIXED);
- } finally {
- typedArray.recycle();
- }
-
- initView(context);
- }
-
- private void initView(Context context) {
- ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR);
- if (mIndicatorType == 0) {
- for (int i = 0; i < mPinLength; i++) {
- View dot = new View(context);
- emptyDot(dot);
-
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mDotDiameter,
- mDotDiameter);
- params.setMargins(mDotSpacing, 0, mDotSpacing, 0);
- dot.setLayoutParams(params);
-
- addView(dot);
- }
- } else if (mIndicatorType == 2) {
- setLayoutTransition(new LayoutTransition());
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- // If the indicator type is not fixed
- if (mIndicatorType != 0) {
- ViewGroup.LayoutParams params = this.getLayoutParams();
- params.height = mDotDiameter;
- requestLayout();
- }
- }
-
- void updateDot(int length) {
- if (mIndicatorType == 0) {
- if (length > 0) {
- if (length > mPreviousLength) {
- fillDot(getChildAt(length - 1));
- } else {
- emptyDot(getChildAt(length));
- }
- mPreviousLength = length;
- } else {
- // When {@code mPinLength} is 0, we need to reset all the views back to empty
- for (int i = 0; i < getChildCount(); i++) {
- View v = getChildAt(i);
- emptyDot(v);
- }
- mPreviousLength = 0;
- }
- } else {
- if (length > 0) {
- if (length > mPreviousLength) {
- View dot = new View(getContext());
- fillDot(dot);
-
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mDotDiameter,
- mDotDiameter);
- params.setMargins(mDotSpacing, 0, mDotSpacing, 0);
- dot.setLayoutParams(params);
-
- addView(dot, length - 1);
- } else {
- removeViewAt(length);
- }
- mPreviousLength = length;
- } else {
- removeAllViews();
- mPreviousLength = 0;
- }
- }
- }
-
- private void emptyDot(View dot) {
- dot.setBackgroundResource(mEmptyDrawable);
- }
-
- private void fillDot(View dot) {
- dot.setBackgroundResource(mFillDrawable);
- }
-
- public int getPinLength() {
- return mPinLength;
- }
-
- public void setPinLength(int pinLength) {
- this.mPinLength = pinLength;
- removeAllViews();
- initView(getContext());
- }
-
- public
- @IndicatorType
- int getIndicatorType() {
- return mIndicatorType;
- }
-
- public void setIndicatorType(@IndicatorType int type) {
- this.mIndicatorType = type;
- removeAllViews();
- initView(getContext());
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/IndicatorDots.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/IndicatorDots.kt
new file mode 100644
index 00000000..0c5dfd93
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/IndicatorDots.kt
@@ -0,0 +1,195 @@
+package com.andrognito.pinlockview
+
+import android.animation.LayoutTransition
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.LinearLayout
+import androidx.annotation.IntDef
+import androidx.core.view.ViewCompat
+
+/**
+ * It represents a set of indicator dots which when attached with [PinLockView]
+ * can be used to indicate the current length of the input
+ *
+ *
+ * Created by aritraroy on 01/06/16.
+ */
+class IndicatorDots @JvmOverloads constructor(context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
+ private var mDotDiameter: Int = 0
+ private var mDotSpacing: Int = 0
+ private var mFillDrawable: Int = 0
+ private var mEmptyDrawable: Int = 0
+ private var mErrorDrawable: Int = 0
+ private var mSuccessDrawable: Int = 0
+ private var mPinLength: Int = 0
+ private var mIndicatorType: Int = 0
+ private var mPreviousLength: Int = 0
+
+ var pinLength: Int
+ get() = mPinLength
+ set(pinLength) {
+ this.mPinLength = pinLength
+ removeAllViews()
+ initView(context)
+ }
+
+ var indicatorType: Int
+ @IndicatorType
+ get() = mIndicatorType
+ set(@IndicatorType type) {
+ this.mIndicatorType = type
+ removeAllViews()
+ initView(context)
+ }
+
+ init {
+
+ val typedArray = context.obtainStyledAttributes(attrs, R.styleable.PinLockView)
+
+ try {
+ mDotDiameter = typedArray.getDimension(R.styleable.PinLockView_dotDiameter, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_diameter)).toInt()
+ mDotSpacing = typedArray.getDimension(R.styleable.PinLockView_dotSpacing, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_dot_spacing)).toInt()
+ mFillDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotFilledBackground,
+ R.drawable.dot_filled)
+ mErrorDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotFilledBackground,
+ R.drawable.dot_error)
+ mSuccessDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotFilledBackground,
+ R.drawable.dot_success)
+ mEmptyDrawable = typedArray.getResourceId(R.styleable.PinLockView_dotEmptyBackground,
+ R.drawable.dot_empty)
+ mPinLength = typedArray.getInt(R.styleable.PinLockView_pinLength, DEFAULT_PIN_LENGTH)
+ mIndicatorType = typedArray.getInt(R.styleable.PinLockView_indicatorType,
+ IndicatorType.FIXED)
+ } finally {
+ typedArray.recycle()
+ }
+
+ initView(context)
+ }
+
+ private fun initView(context: Context) {
+ ViewCompat.setLayoutDirection(this, ViewCompat.LAYOUT_DIRECTION_LTR)
+ if (mIndicatorType == 0) {
+ for (i in 0 until mPinLength) {
+ val dot = View(context)
+ emptyDot(dot)
+
+ val params = LayoutParams(mDotDiameter,
+ mDotDiameter)
+ params.setMargins(mDotSpacing, 0, mDotSpacing, 0)
+ dot.layoutParams = params
+
+ addView(dot)
+ }
+ } else if (mIndicatorType == 2) {
+ layoutTransition = LayoutTransition()
+ }
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ // If the indicator type is not fixed
+ if (mIndicatorType != 0) {
+ val params = this.layoutParams
+ params.height = mDotDiameter
+ requestLayout()
+ }
+ }
+
+ internal fun updateDot(length: Int) {
+ if (mIndicatorType == 0) {
+ if (length > 0) {
+ if (length > mPreviousLength) {
+ fillDot(getChildAt(length - 1))
+ } else {
+ emptyDot(getChildAt(length))
+ }
+ mPreviousLength = length
+ } else {
+ // When {@code mPinLength} is 0, we need to reset all the views back to empty
+ for (i in 0 until childCount) {
+ val v = getChildAt(i)
+ emptyDot(v)
+ }
+ mPreviousLength = 0
+ }
+ } else {
+ if (length > 0) {
+ if (length > mPreviousLength) {
+ val dot = View(context)
+ fillDot(dot)
+
+ val params = LayoutParams(mDotDiameter,
+ mDotDiameter)
+ params.setMargins(mDotSpacing, 0, mDotSpacing, 0)
+ dot.layoutParams = params
+
+ addView(dot, length - 1)
+ } else {
+ removeViewAt(length)
+ }
+ mPreviousLength = length
+ } else {
+ removeAllViews()
+ mPreviousLength = 0
+ }
+ }
+ }
+
+ fun setErrorDots() {
+ for (i in 0 until childCount) {
+ val v = getChildAt(i)
+ errorDot(v)
+ }
+ }
+
+ fun setSuccessDots() {
+ for (i in 0 until childCount) {
+ val v = getChildAt(i)
+ successDot(v)
+ }
+ }
+
+ fun setDefaultDots() {
+ // for (int i = 0; i < getChildCount(); i++) {
+ // View v = getChildAt(i);
+ // emptyDot(v);
+ // }
+ removeAllViews()
+ initView(context)
+ mPreviousLength = 0
+ }
+
+ private fun emptyDot(dot: View) {
+ dot.setBackgroundResource(mEmptyDrawable)
+ }
+
+ private fun fillDot(dot: View) {
+ dot.setBackgroundResource(mFillDrawable)
+ }
+
+ private fun errorDot(dot: View) {
+ dot.setBackgroundResource(mErrorDrawable)
+ }
+
+ private fun successDot(dot: View) {
+ dot.setBackgroundResource(mSuccessDrawable)
+ }
+
+ @IntDef(IndicatorType.FIXED, IndicatorType.FILL, IndicatorType.FILL_WITH_ANIMATION)
+ @Retention(AnnotationRetention.SOURCE)
+ annotation class IndicatorType {
+ companion object {
+ const val FIXED = 0
+ const val FILL = 1
+ const val FILL_WITH_ANIMATION = 2
+ }
+ }
+
+ companion object {
+ private const val DEFAULT_PIN_LENGTH = 4
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.java b/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.java
deleted file mode 100644
index 3abbd1a9..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.andrognito.pinlockview;
-
-import android.graphics.Rect;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-/**
- * Created by aritraroy on 31/05/16.
- */
-public class ItemSpaceDecoration extends RecyclerView.ItemDecoration {
-
- private final int mHorizontalSpaceWidth;
- private final int mVerticalSpaceHeight;
- private final int mSpanCount;
- private final boolean mIncludeEdge;
-
- public ItemSpaceDecoration(int horizontalSpaceWidth, int verticalSpaceHeight, int spanCount, boolean includeEdge) {
- this.mHorizontalSpaceWidth = horizontalSpaceWidth;
- this.mVerticalSpaceHeight = verticalSpaceHeight;
- this.mSpanCount = spanCount;
- this.mIncludeEdge = includeEdge;
- }
-
- @Override
- public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
-
- int position = parent.getChildAdapterPosition(view);
- int column = position % mSpanCount;
-
- if (mIncludeEdge) {
- outRect.left = mHorizontalSpaceWidth - column * mHorizontalSpaceWidth / mSpanCount;
- outRect.right = (column + 1) * mHorizontalSpaceWidth / mSpanCount;
-
- if (position < mSpanCount) {
- outRect.top = mVerticalSpaceHeight;
- }
- outRect.bottom = mVerticalSpaceHeight;
- } else {
- outRect.left = column * mHorizontalSpaceWidth / mSpanCount;
- outRect.right = mHorizontalSpaceWidth - (column + 1) * mHorizontalSpaceWidth / mSpanCount;
- if (position >= mSpanCount) {
- outRect.top = mVerticalSpaceHeight;
- }
- }
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.kt
new file mode 100644
index 00000000..e7060049
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/ItemSpaceDecoration.kt
@@ -0,0 +1,37 @@
+package com.andrognito.pinlockview
+
+import android.graphics.Rect
+import android.view.View
+
+import androidx.recyclerview.widget.RecyclerView
+
+/**
+ * Created by aritraroy on 31/05/16.
+ */
+class ItemSpaceDecoration(private val mHorizontalSpaceWidth: Int,
+ private val mVerticalSpaceHeight: Int,
+ private val mSpanCount: Int,
+ private val mIncludeEdge: Boolean) : RecyclerView.ItemDecoration() {
+
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+
+ val position = parent.getChildAdapterPosition(view)
+ val column = position % mSpanCount
+
+ if (mIncludeEdge) {
+ outRect.left = mHorizontalSpaceWidth - column * mHorizontalSpaceWidth / mSpanCount
+ outRect.right = (column + 1) * mHorizontalSpaceWidth / mSpanCount
+
+ if (position < mSpanCount) {
+ outRect.top = mVerticalSpaceHeight
+ }
+ outRect.bottom = mVerticalSpaceHeight
+ } else {
+ outRect.left = column * mHorizontalSpaceWidth / mSpanCount
+ outRect.right = mHorizontalSpaceWidth - (column + 1) * mHorizontalSpaceWidth / mSpanCount
+ if (position >= mSpanCount) {
+ outRect.top = mVerticalSpaceHeight
+ }
+ }
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.java b/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.java
deleted file mode 100644
index eac00a54..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.andrognito.pinlockview;
-
-import android.content.Context;
-import android.support.v7.widget.GridLayoutManager;
-import android.util.AttributeSet;
-
-/**
- * Used to always maintain an LTR layout no matter what is the real device's layout direction
- * to avoid an unwanted reversed direction in RTL devices
- * Created by Idan on 7/6/2017.
- */
-
-public class LTRGridLayoutManager extends GridLayoutManager {
-
- public LTRGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public LTRGridLayoutManager(Context context, int spanCount) {
- super(context, spanCount);
- }
-
- public LTRGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
- super(context, spanCount, orientation, reverseLayout);
- }
-
- @Override
- protected boolean isLayoutRTL(){
- return false;
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.kt
new file mode 100644
index 00000000..45e3333c
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/LTRGridLayoutManager.kt
@@ -0,0 +1,26 @@
+package com.andrognito.pinlockview
+
+import android.content.Context
+import android.util.AttributeSet
+
+import androidx.recyclerview.widget.GridLayoutManager
+
+/**
+ * Used to always maintain an LTR layout no matter what is the real device's layout direction
+ * to avoid an unwanted reversed direction in RTL devices
+ * Created by Idan on 7/6/2017.
+ */
+class LTRGridLayoutManager : GridLayoutManager {
+
+ constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int)
+ : super(context, attrs, defStyleAttr, defStyleRes)
+
+ constructor(context: Context, spanCount: Int) : super(context, spanCount)
+
+ constructor(context: Context, spanCount: Int, orientation: Int, reverseLayout: Boolean)
+ : super(context, spanCount, orientation, reverseLayout)
+
+ override fun isLayoutRTL(): Boolean {
+ return false
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.java b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.java
deleted file mode 100644
index 1df5c3a7..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.java
+++ /dev/null
@@ -1,262 +0,0 @@
-package com.andrognito.pinlockview;
-
-import android.content.Context;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.os.Build;
-import android.support.v7.widget.RecyclerView;
-import android.util.TypedValue;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-/**
- * Created by aritraroy on 31/05/16.
- */
-public class PinLockAdapter extends RecyclerView.Adapter {
-
- private static final int VIEW_TYPE_NUMBER = 0;
- private static final int VIEW_TYPE_DELETE = 1;
-
- private Context mContext;
- private CustomizationOptionsBundle mCustomizationOptionsBundle;
- private OnNumberClickListener mOnNumberClickListener;
- private OnDeleteClickListener mOnDeleteClickListener;
- private int mPinLength;
-
- private int[] mKeyValues;
-
- public PinLockAdapter(Context context) {
- this.mContext = context;
- this.mKeyValues = getAdjustKeyValues(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
- }
-
- @Override
- public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- RecyclerView.ViewHolder viewHolder;
- LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-
- if (viewType == VIEW_TYPE_NUMBER) {
- View view = inflater.inflate(R.layout.layout_number_item, parent, false);
- viewHolder = new NumberViewHolder(view);
- } else {
- View view = inflater.inflate(R.layout.layout_delete_item, parent, false);
- viewHolder = new DeleteViewHolder(view);
- }
- return viewHolder;
- }
-
- @Override
- public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
- if (holder.getItemViewType() == VIEW_TYPE_NUMBER) {
- NumberViewHolder vh1 = (NumberViewHolder) holder;
- configureNumberButtonHolder(vh1, position);
- } else if (holder.getItemViewType() == VIEW_TYPE_DELETE) {
- DeleteViewHolder vh2 = (DeleteViewHolder) holder;
- configureDeleteButtonHolder(vh2);
- }
- }
-
- private void configureNumberButtonHolder(NumberViewHolder holder, int position) {
- if (holder != null) {
- if (position == 9) {
- holder.mNumberButton.setVisibility(View.GONE);
- } else {
- holder.mNumberButton.setText(String.valueOf(mKeyValues[position]));
- holder.mNumberButton.setVisibility(View.VISIBLE);
- holder.mNumberButton.setTag(mKeyValues[position]);
- }
-
- if (mCustomizationOptionsBundle != null) {
- holder.mNumberButton.setTextColor(mCustomizationOptionsBundle.getTextColor());
- if (mCustomizationOptionsBundle.getButtonBackgroundDrawable() != null) {
- if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
- holder.mNumberButton.setBackgroundDrawable(
- mCustomizationOptionsBundle.getButtonBackgroundDrawable());
- } else {
- holder.mNumberButton.setBackground(
- mCustomizationOptionsBundle.getButtonBackgroundDrawable());
- }
- }
- holder.mNumberButton.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- mCustomizationOptionsBundle.getTextSize());
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- mCustomizationOptionsBundle.getButtonSize(),
- mCustomizationOptionsBundle.getButtonSize());
- holder.mNumberButton.setLayoutParams(params);
- }
- }
- }
-
- private void configureDeleteButtonHolder(DeleteViewHolder holder) {
- if (holder != null) {
- if (mCustomizationOptionsBundle.isShowDeleteButton() && mPinLength > 0) {
- holder.mButtonImage.setVisibility(View.VISIBLE);
- if (mCustomizationOptionsBundle.getDeleteButtonDrawable() != null) {
- holder.mButtonImage.setImageDrawable(mCustomizationOptionsBundle.getDeleteButtonDrawable());
- }
- holder.mButtonImage.setColorFilter(mCustomizationOptionsBundle.getTextColor(),
- PorterDuff.Mode.SRC_ATOP);
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- mCustomizationOptionsBundle.getDeleteButtonSize(),
- mCustomizationOptionsBundle.getDeleteButtonSize());
- holder.mButtonImage.setLayoutParams(params);
- } else {
- holder.mButtonImage.setVisibility(View.GONE);
- }
- }
- }
-
- @Override
- public int getItemCount() {
- return 12;
- }
-
- @Override
- public int getItemViewType(int position) {
- if (position == getItemCount() - 1) {
- return VIEW_TYPE_DELETE;
- }
- return VIEW_TYPE_NUMBER;
- }
-
- public int getPinLength() {
- return mPinLength;
- }
-
- public void setPinLength(int pinLength) {
- this.mPinLength = pinLength;
- }
-
- public int[] getKeyValues() {
- return mKeyValues;
- }
-
- public void setKeyValues(int[] keyValues) {
- this.mKeyValues = getAdjustKeyValues(keyValues);
- notifyDataSetChanged();
- }
-
- private int[] getAdjustKeyValues(int[] keyValues) {
- int[] adjustedKeyValues = new int[keyValues.length + 1];
- for (int i = 0; i < keyValues.length; i++) {
- if (i < 9) {
- adjustedKeyValues[i] = keyValues[i];
- } else {
- adjustedKeyValues[i] = -1;
- adjustedKeyValues[i + 1] = keyValues[i];
- }
- }
- return adjustedKeyValues;
- }
-
- public OnNumberClickListener getOnItemClickListener() {
- return mOnNumberClickListener;
- }
-
- public void setOnItemClickListener(OnNumberClickListener onNumberClickListener) {
- this.mOnNumberClickListener = onNumberClickListener;
- }
-
- public OnDeleteClickListener getOnDeleteClickListener() {
- return mOnDeleteClickListener;
- }
-
- public void setOnDeleteClickListener(OnDeleteClickListener onDeleteClickListener) {
- this.mOnDeleteClickListener = onDeleteClickListener;
- }
-
- public CustomizationOptionsBundle getCustomizationOptions() {
- return mCustomizationOptionsBundle;
- }
-
- public void setCustomizationOptions(CustomizationOptionsBundle customizationOptionsBundle) {
- this.mCustomizationOptionsBundle = customizationOptionsBundle;
- }
-
- public class NumberViewHolder extends RecyclerView.ViewHolder {
- Button mNumberButton;
-
- public NumberViewHolder(final View itemView) {
- super(itemView);
- mNumberButton = (Button) itemView.findViewById(R.id.button);
- mNumberButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mOnNumberClickListener != null) {
- mOnNumberClickListener.onNumberClicked((Integer) v.getTag());
- }
- }
- });
- }
- }
-
- public class DeleteViewHolder extends RecyclerView.ViewHolder {
- LinearLayout mDeleteButton;
- ImageView mButtonImage;
-
- public DeleteViewHolder(final View itemView) {
- super(itemView);
- mDeleteButton = (LinearLayout) itemView.findViewById(R.id.button);
- mButtonImage = (ImageView) itemView.findViewById(R.id.buttonImage);
-
- if (mCustomizationOptionsBundle.isShowDeleteButton() && mPinLength > 0) {
- mDeleteButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mOnDeleteClickListener != null) {
- mOnDeleteClickListener.onDeleteClicked();
- }
- }
- });
-
- mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- if (mOnDeleteClickListener != null) {
- mOnDeleteClickListener.onDeleteLongClicked();
- }
- return true;
- }
- });
-
- mDeleteButton.setOnTouchListener(new View.OnTouchListener() {
- private Rect rect;
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- mButtonImage.setColorFilter(mCustomizationOptionsBundle
- .getDeleteButtonPressesColor());
- rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
- }
- if (event.getAction() == MotionEvent.ACTION_UP) {
- mButtonImage.clearColorFilter();
- }
- if (event.getAction() == MotionEvent.ACTION_MOVE) {
- if (!rect.contains(v.getLeft() + (int) event.getX(),
- v.getTop() + (int) event.getY())) {
- mButtonImage.clearColorFilter();
- }
- }
- return false;
- }
- });
- }
- }
- }
-
- public interface OnNumberClickListener {
- void onNumberClicked(int keyValue);
- }
-
- public interface OnDeleteClickListener {
- void onDeleteClicked();
-
- void onDeleteLongClicked();
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.kt
new file mode 100644
index 00000000..9be92af9
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockAdapter.kt
@@ -0,0 +1,205 @@
+package com.andrognito.pinlockview
+
+import android.content.Context
+import android.graphics.PorterDuff
+import android.graphics.Rect
+import android.util.TypedValue
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.LinearLayout
+
+import androidx.recyclerview.widget.RecyclerView
+
+/**
+ * Created by aritraroy on 31/05/16.
+ */
+class PinLockAdapter(private val mContext: Context) : RecyclerView.Adapter() {
+ var customizationOptions: CustomizationOptionsBundle? = null
+ var onItemClickListener: OnNumberClickListener? = null
+ var onDeleteClickListener: OnDeleteClickListener? = null
+ var pinLength: Int = 0
+
+ private var mKeyValues: IntArray? = null
+
+ var keyValues: IntArray?
+ get() = mKeyValues
+ set(keyValues) {
+ this.mKeyValues = getAdjustKeyValues(keyValues!!)
+ notifyDataSetChanged()
+ }
+
+ init {
+ this.mKeyValues = getAdjustKeyValues(intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 0))
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val viewHolder: RecyclerView.ViewHolder
+ val inflater = LayoutInflater.from(parent.context)
+
+ if (viewType == VIEW_TYPE_NUMBER) {
+ val view = inflater.inflate(R.layout.layout_number_item, parent, false)
+ viewHolder = NumberViewHolder(view)
+ } else {
+ val view = inflater.inflate(R.layout.layout_delete_item, parent, false)
+ viewHolder = DeleteViewHolder(view)
+ }
+ return viewHolder
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ if (holder.itemViewType == VIEW_TYPE_NUMBER) {
+ val vh1 = holder as NumberViewHolder
+ configureNumberButtonHolder(vh1, position)
+ } else if (holder.itemViewType == VIEW_TYPE_DELETE) {
+ val vh2 = holder as DeleteViewHolder
+ configureDeleteButtonHolder(vh2)
+ }
+ }
+
+ private fun configureNumberButtonHolder(holder: NumberViewHolder?, position: Int) {
+ if (holder != null) {
+ if (position == 9) {
+ holder.mNumberButton.visibility = View.GONE
+ } else {
+ holder.mNumberButton.text = mKeyValues!![position].toString()
+ holder.mNumberButton.visibility = View.VISIBLE
+ holder.mNumberButton.tag = mKeyValues!![position]
+ }
+
+ if (customizationOptions != null) {
+ holder.mNumberButton.setTextColor(customizationOptions!!.textColor)
+ if (customizationOptions!!.buttonBackgroundDrawable != null) {
+ holder.mNumberButton.background = customizationOptions!!.buttonBackgroundDrawable
+ }
+ holder.mNumberButton.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ customizationOptions!!.textSize.toFloat())
+ val params = LinearLayout.LayoutParams(
+ customizationOptions!!.buttonSize,
+ customizationOptions!!.buttonSize)
+ holder.mNumberButton.layoutParams = params
+ }
+ }
+ }
+
+ private fun configureDeleteButtonHolder(holder: DeleteViewHolder?) {
+ if (holder != null) {
+ if (customizationOptions!!.isShowDeleteButton && pinLength > 0) {
+ holder.mButtonImage.visibility = View.VISIBLE
+ if (customizationOptions!!.deleteButtonDrawable != null) {
+ holder.mButtonImage.setImageDrawable(customizationOptions!!.deleteButtonDrawable)
+ }
+ holder.mButtonImage.setColorFilter(customizationOptions!!.textColor,
+ PorterDuff.Mode.SRC_ATOP)
+ val params = LinearLayout.LayoutParams(
+ customizationOptions!!.deleteButtonSize,
+ customizationOptions!!.deleteButtonSize)
+ holder.mButtonImage.layoutParams = params
+ } else {
+ holder.mButtonImage.visibility = View.GONE
+ }
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return 12
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return if (position == itemCount - 1) {
+ VIEW_TYPE_DELETE
+ } else VIEW_TYPE_NUMBER
+ }
+
+ private fun getAdjustKeyValues(keyValues: IntArray): IntArray {
+ val adjustedKeyValues = IntArray(keyValues.size + 1)
+ for (i in keyValues.indices) {
+ if (i < 9) {
+ adjustedKeyValues[i] = keyValues[i]
+ } else {
+ adjustedKeyValues[i] = -1
+ adjustedKeyValues[i + 1] = keyValues[i]
+ }
+ }
+ return adjustedKeyValues
+ }
+
+ interface OnNumberClickListener {
+ fun onNumberClicked(keyValue: Int)
+ }
+
+ interface OnDeleteClickListener {
+ fun onDeleteClicked()
+
+ fun onDeleteLongClicked()
+ }
+
+ inner class NumberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ internal var mNumberButton: Button
+
+ init {
+ mNumberButton = itemView.findViewById(R.id.button)
+ mNumberButton.setOnClickListener { v ->
+ if (onItemClickListener != null) {
+ onItemClickListener!!.onNumberClicked(v.tag as Int)
+ }
+ }
+ }
+ }
+
+ inner class DeleteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ internal var mDeleteButton: LinearLayout
+ internal var mButtonImage: ImageView
+
+ init {
+ mDeleteButton = itemView.findViewById(R.id.button)
+ mButtonImage = itemView.findViewById(R.id.buttonImage)
+
+ if (customizationOptions!!.isShowDeleteButton && pinLength > 0) {
+ mDeleteButton.setOnClickListener {
+ if (onDeleteClickListener != null) {
+ onDeleteClickListener!!.onDeleteClicked()
+ }
+ }
+
+ mDeleteButton.setOnLongClickListener {
+ if (onDeleteClickListener != null) {
+ onDeleteClickListener!!.onDeleteLongClicked()
+ }
+ true
+ }
+
+ mDeleteButton.setOnTouchListener(object : View.OnTouchListener {
+ private var rect: Rect? = null
+
+ override fun onTouch(v: View, event: MotionEvent): Boolean {
+ if (event.action == MotionEvent.ACTION_DOWN) {
+ mButtonImage.setColorFilter(customizationOptions!!
+ .deleteButtonPressesColor)
+ rect = Rect(v.left, v.top, v.right, v.bottom)
+ }
+ if (event.action == MotionEvent.ACTION_UP) {
+ mButtonImage.clearColorFilter()
+ }
+ if (event.action == MotionEvent.ACTION_MOVE) {
+ if (!rect!!.contains(v.left + event.x.toInt(),
+ v.top + event.y.toInt())) {
+ mButtonImage.clearColorFilter()
+ }
+ }
+ return false
+ }
+ })
+ }
+ }
+ }
+
+ companion object {
+
+ private const val VIEW_TYPE_NUMBER = 0
+ private const val VIEW_TYPE_DELETE = 1
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.java b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.kt
similarity index 63%
rename from pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.java
rename to pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.kt
index fcb00f9f..7ad08c46 100644
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.java
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockListener.kt
@@ -1,12 +1,12 @@
-package com.andrognito.pinlockview;
+package com.andrognito.pinlockview
/**
* The listener that triggers callbacks for various events
- * in the {@link PinLockView}
+ * in the [PinLockView]
*
* Created by aritraroy on 31/05/16.
*/
-public interface PinLockListener {
+interface PinLockListener {
/**
* Triggers when the complete pin is entered,
@@ -14,19 +14,19 @@ public interface PinLockListener {
*
* @param pin the complete pin
*/
- void onComplete(String pin);
+ fun onComplete(pin: String)
/**
* Triggers when the pin is empty after manual deletion
*/
- void onEmpty();
+ fun onEmpty()
/**
- * Triggers on a key press on the {@link PinLockView}
+ * Triggers on a key press on the [PinLockView]
*
* @param pinLength the current pin length
* @param intermediatePin the intermediate pin
*/
- void onPinChange(int pinLength, String intermediatePin);
+ fun onPinChange(pinLength: Int, intermediatePin: String)
}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.java b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.java
deleted file mode 100644
index 72eade71..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.java
+++ /dev/null
@@ -1,432 +0,0 @@
-package com.andrognito.pinlockview;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.RecyclerView;
-import android.util.AttributeSet;
-
-/**
- * Represents a numeric lock view which can used to taken numbers as input.
- * The length of the input can be customized using {@link PinLockView#setPinLength(int)}, the default value being 4
- *
- * It can also be used as dial pad for taking number inputs.
- * Optionally, {@link IndicatorDots} can be attached to this view to indicate the length of the input taken
- * Created by aritraroy on 31/05/16.
- */
-public class PinLockView extends RecyclerView {
-
- private static final int DEFAULT_PIN_LENGTH = 4;
- private static final int[] DEFAULT_KEY_SET = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
-
- private String mPin = "";
- private int mPinLength;
- private int mHorizontalSpacing, mVerticalSpacing;
- private int mTextColor, mDeleteButtonPressedColor;
- private int mTextSize, mButtonSize, mDeleteButtonSize;
- private Drawable mButtonBackgroundDrawable;
- private Drawable mDeleteButtonDrawable;
- private boolean mShowDeleteButton;
-
- private IndicatorDots mIndicatorDots;
- private PinLockAdapter mAdapter;
- private PinLockListener mPinLockListener;
- private CustomizationOptionsBundle mCustomizationOptionsBundle;
- private int[] mCustomKeySet;
-
- private PinLockAdapter.OnNumberClickListener mOnNumberClickListener
- = new PinLockAdapter.OnNumberClickListener() {
- @Override
- public void onNumberClicked(int keyValue) {
- if (mPin.length() < getPinLength()) {
- mPin = mPin.concat(String.valueOf(keyValue));
-
- if (isIndicatorDotsAttached()) {
- mIndicatorDots.updateDot(mPin.length());
- }
-
- if (mPin.length() == 1) {
- mAdapter.setPinLength(mPin.length());
- mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1);
- }
-
- if (mPinLockListener != null) {
- if (mPin.length() == mPinLength) {
- mPinLockListener.onComplete(mPin);
- } else {
- mPinLockListener.onPinChange(mPin.length(), mPin);
- }
- }
- } else {
- if (!isShowDeleteButton()) {
- resetPinLockView();
- mPin = mPin.concat(String.valueOf(keyValue));
-
- if (isIndicatorDotsAttached()) {
- mIndicatorDots.updateDot(mPin.length());
- }
-
- if (mPinLockListener != null) {
- mPinLockListener.onPinChange(mPin.length(), mPin);
- }
-
- } else {
- if (mPinLockListener != null) {
- mPinLockListener.onComplete(mPin);
- }
- }
- }
- }
- };
-
- private PinLockAdapter.OnDeleteClickListener mOnDeleteClickListener
- = new PinLockAdapter.OnDeleteClickListener() {
- @Override
- public void onDeleteClicked() {
- if (mPin.length() > 0) {
- mPin = mPin.substring(0, mPin.length() - 1);
-
- if (isIndicatorDotsAttached()) {
- mIndicatorDots.updateDot(mPin.length());
- }
-
- if (mPin.length() == 0) {
- mAdapter.setPinLength(mPin.length());
- mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1);
- }
-
- if (mPinLockListener != null) {
- if (mPin.length() == 0) {
- mPinLockListener.onEmpty();
- clearInternalPin();
- } else {
- mPinLockListener.onPinChange(mPin.length(), mPin);
- }
- }
- } else {
- if (mPinLockListener != null) {
- mPinLockListener.onEmpty();
- }
- }
- }
-
- @Override
- public void onDeleteLongClicked() {
- resetPinLockView();
- if (mPinLockListener != null) {
- mPinLockListener.onEmpty();
- }
- }
- };
-
- public PinLockView(Context context) {
- super(context);
- init(null, 0);
- }
-
- public PinLockView(Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- init(attrs, 0);
- }
-
- public PinLockView(Context context, @Nullable AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(attrs, defStyle);
- }
-
- private void init(AttributeSet attributeSet, int defStyle) {
-
- TypedArray typedArray = getContext().obtainStyledAttributes(attributeSet, R.styleable.PinLockView);
-
- try {
- mPinLength = typedArray.getInt(R.styleable.PinLockView_pinLength, DEFAULT_PIN_LENGTH);
- mHorizontalSpacing = (int) typedArray.getDimension(R.styleable.PinLockView_keypadHorizontalSpacing, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_horizontal_spacing));
- mVerticalSpacing = (int) typedArray.getDimension(R.styleable.PinLockView_keypadVerticalSpacing, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_vertical_spacing));
- mTextColor = typedArray.getColor(R.styleable.PinLockView_keypadTextColor, ResourceUtils.getColor(getContext(), R.color.white));
- mTextSize = (int) typedArray.getDimension(R.styleable.PinLockView_keypadTextSize, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_text_size));
- mButtonSize = (int) typedArray.getDimension(R.styleable.PinLockView_keypadButtonSize, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_button_size));
- mDeleteButtonSize = (int) typedArray.getDimension(R.styleable.PinLockView_keypadDeleteButtonSize, ResourceUtils.getDimensionInPx(getContext(), R.dimen.default_delete_button_size));
- mButtonBackgroundDrawable = typedArray.getDrawable(R.styleable.PinLockView_keypadButtonBackgroundDrawable);
- mDeleteButtonDrawable = typedArray.getDrawable(R.styleable.PinLockView_keypadDeleteButtonDrawable);
- mShowDeleteButton = typedArray.getBoolean(R.styleable.PinLockView_keypadShowDeleteButton, true);
- mDeleteButtonPressedColor = typedArray.getColor(R.styleable.PinLockView_keypadDeleteButtonPressedColor, ResourceUtils.getColor(getContext(), R.color.greyish));
- } finally {
- typedArray.recycle();
- }
-
- mCustomizationOptionsBundle = new CustomizationOptionsBundle();
- mCustomizationOptionsBundle.setTextColor(mTextColor);
- mCustomizationOptionsBundle.setTextSize(mTextSize);
- mCustomizationOptionsBundle.setButtonSize(mButtonSize);
- mCustomizationOptionsBundle.setButtonBackgroundDrawable(mButtonBackgroundDrawable);
- mCustomizationOptionsBundle.setDeleteButtonDrawable(mDeleteButtonDrawable);
- mCustomizationOptionsBundle.setDeleteButtonSize(mDeleteButtonSize);
- mCustomizationOptionsBundle.setShowDeleteButton(mShowDeleteButton);
- mCustomizationOptionsBundle.setDeleteButtonPressesColor(mDeleteButtonPressedColor);
-
- initView();
- }
-
- private void initView() {
- setLayoutManager(new LTRGridLayoutManager(getContext(), 3));
-
- mAdapter = new PinLockAdapter(getContext());
- mAdapter.setOnItemClickListener(mOnNumberClickListener);
- mAdapter.setOnDeleteClickListener(mOnDeleteClickListener);
- mAdapter.setCustomizationOptions(mCustomizationOptionsBundle);
- setAdapter(mAdapter);
-
- addItemDecoration(new ItemSpaceDecoration(mHorizontalSpacing, mVerticalSpacing, 3, false));
- setOverScrollMode(OVER_SCROLL_NEVER);
- }
-
- /**
- * Sets a {@link PinLockListener} to the to listen to pin update events
- *
- * @param pinLockListener the listener
- */
- public void setPinLockListener(PinLockListener pinLockListener) {
- this.mPinLockListener = pinLockListener;
- }
-
- /**
- * Get the length of the current pin length
- *
- * @return the length of the pin
- */
- public int getPinLength() {
- return mPinLength;
- }
-
- /**
- * Sets the pin length dynamically
- *
- * @param pinLength the pin length
- */
- public void setPinLength(int pinLength) {
- this.mPinLength = pinLength;
-
- if (isIndicatorDotsAttached()) {
- mIndicatorDots.setPinLength(pinLength);
- }
- }
-
- /**
- * Get the text color in the buttons
- *
- * @return the text color
- */
- public int getTextColor() {
- return mTextColor;
- }
-
- /**
- * Set the text color of the buttons dynamically
- *
- * @param textColor the text color
- */
- public void setTextColor(int textColor) {
- this.mTextColor = textColor;
- mCustomizationOptionsBundle.setTextColor(textColor);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the size of the text in the buttons
- *
- * @return the size of the text in pixels
- */
- public int getTextSize() {
- return mTextSize;
- }
-
- /**
- * Set the size of text in pixels
- *
- * @param textSize the text size in pixels
- */
- public void setTextSize(int textSize) {
- this.mTextSize = textSize;
- mCustomizationOptionsBundle.setTextSize(textSize);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the size of the pin buttons
- *
- * @return the size of the button in pixels
- */
- public int getButtonSize() {
- return mButtonSize;
- }
-
- /**
- * Set the size of the pin buttons dynamically
- *
- * @param buttonSize the button size
- */
- public void setButtonSize(int buttonSize) {
- this.mButtonSize = buttonSize;
- mCustomizationOptionsBundle.setButtonSize(buttonSize);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the current background drawable of the buttons, can be null
- *
- * @return the background drawable
- */
- public Drawable getButtonBackgroundDrawable() {
- return mButtonBackgroundDrawable;
- }
-
- /**
- * Set the background drawable of the buttons dynamically
- *
- * @param buttonBackgroundDrawable the background drawable
- */
- public void setButtonBackgroundDrawable(Drawable buttonBackgroundDrawable) {
- this.mButtonBackgroundDrawable = buttonBackgroundDrawable;
- mCustomizationOptionsBundle.setButtonBackgroundDrawable(buttonBackgroundDrawable);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the drawable of the delete button
- *
- * @return the delete button drawable
- */
- public Drawable getDeleteButtonDrawable() {
- return mDeleteButtonDrawable;
- }
-
- /**
- * Set the drawable of the delete button dynamically
- *
- * @param deleteBackgroundDrawable the delete button drawable
- */
- public void setDeleteButtonDrawable(Drawable deleteBackgroundDrawable) {
- this.mDeleteButtonDrawable = deleteBackgroundDrawable;
- mCustomizationOptionsBundle.setDeleteButtonDrawable(deleteBackgroundDrawable);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the delete button size in pixels
- *
- * @return size in pixels
- */
- public int getDeleteButtonSize() {
- return mDeleteButtonSize;
- }
-
- /**
- * Set the size of the delete button in pixels
- *
- * @param deleteButtonSize size in pixels
- */
- public void setDeleteButtonSize(int deleteButtonSize) {
- this.mDeleteButtonSize = deleteButtonSize;
- mCustomizationOptionsBundle.setDeleteButtonSize(deleteButtonSize);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Is the delete button shown
- *
- * @return returns true if shown, false otherwise
- */
- public boolean isShowDeleteButton() {
- return mShowDeleteButton;
- }
-
- /**
- * Dynamically set if the delete button should be shown
- *
- * @param showDeleteButton true if the delete button should be shown, false otherwise
- */
- public void setShowDeleteButton(boolean showDeleteButton) {
- this.mShowDeleteButton = showDeleteButton;
- mCustomizationOptionsBundle.setShowDeleteButton(showDeleteButton);
- mAdapter.notifyDataSetChanged();
- }
-
- /**
- * Get the delete button pressed/focused state color
- *
- * @return color of the button
- */
- public int getDeleteButtonPressedColor() {
- return mDeleteButtonPressedColor;
- }
-
- /**
- * Set the pressed/focused state color of the delete button
- *
- * @param deleteButtonPressedColor the color of the delete button
- */
- public void setDeleteButtonPressedColor(int deleteButtonPressedColor) {
- this.mDeleteButtonPressedColor = deleteButtonPressedColor;
- mCustomizationOptionsBundle.setDeleteButtonPressesColor(deleteButtonPressedColor);
- mAdapter.notifyDataSetChanged();
- }
-
- public int[] getCustomKeySet() {
- return mCustomKeySet;
- }
-
- public void setCustomKeySet(int[] customKeySet) {
- this.mCustomKeySet = customKeySet;
-
- if (mAdapter != null) {
- mAdapter.setKeyValues(customKeySet);
- }
- }
-
- public void enableLayoutShuffling() {
- this.mCustomKeySet = ShuffleArrayUtils.shuffle(DEFAULT_KEY_SET);
-
- if (mAdapter != null) {
- mAdapter.setKeyValues(mCustomKeySet);
- }
- }
-
- private void clearInternalPin() {
- mPin = "";
- }
-
- /**
- * Resets the {@link PinLockView}, clearing the entered pin
- * and resetting the {@link IndicatorDots} if attached
- */
- public void resetPinLockView() {
-
- clearInternalPin();
-
- mAdapter.setPinLength(mPin.length());
- mAdapter.notifyItemChanged(mAdapter.getItemCount() - 1);
-
- if (mIndicatorDots != null) {
- mIndicatorDots.updateDot(mPin.length());
- }
- }
-
- /**
- * Returns true if {@link IndicatorDots} are attached to {@link PinLockView}
- *
- * @return true if attached, false otherwise
- */
- public boolean isIndicatorDotsAttached() {
- return mIndicatorDots != null;
- }
-
- /**
- * Attaches {@link IndicatorDots} to {@link PinLockView}
- *
- * @param mIndicatorDots the view to attach
- */
- public void attachIndicatorDots(IndicatorDots mIndicatorDots) {
- this.mIndicatorDots = mIndicatorDots;
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.kt
new file mode 100644
index 00000000..b25e01e9
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/PinLockView.kt
@@ -0,0 +1,411 @@
+package com.andrognito.pinlockview
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+
+/**
+ * Represents a numeric lock view which can used to taken numbers as input.
+ * The length of the input can be customized using [PinLockView.setPinLength], the default value being 4
+ *
+ *
+ * It can also be used as dial pad for taking number inputs.
+ * Optionally, [IndicatorDots] can be attached to this view to indicate the length of the input taken
+ * Created by aritraroy on 31/05/16.
+ */
+class PinLockView : RecyclerView {
+
+ private var mPin = ""
+ private var mPinLength: Int = 0
+ private var mHorizontalSpacing: Int = 0
+ private var mVerticalSpacing: Int = 0
+ private var mTextColor: Int = 0
+ private var mDeleteButtonPressedColor: Int = 0
+ private var mTextSize: Int = 0
+ private var mButtonSize: Int = 0
+ private var mDeleteButtonSize: Int = 0
+ private var mButtonBackgroundDrawable: Drawable? = null
+ private var mDeleteButtonDrawable: Drawable? = null
+ private var mShowDeleteButton: Boolean = false
+
+ private var mIndicatorDots: IndicatorDots? = null
+ private var mAdapter: PinLockAdapter? = null
+ private var mPinLockListener: PinLockListener? = null
+ private var mCustomizationOptionsBundle: CustomizationOptionsBundle? = null
+ private var mCustomKeySet: IntArray? = null
+
+ private val mOnNumberClickListener = object : PinLockAdapter.OnNumberClickListener {
+ override fun onNumberClicked(keyValue: Int) {
+
+ if (mPin.length < pinLength) {
+ mPin += keyValue.toString()
+
+ if (isIndicatorDotsAttached) {
+ mIndicatorDots!!.updateDot(mPin.length)
+ }
+
+ if (mPin.length == 1) {
+ mAdapter!!.pinLength = mPin.length
+ mAdapter!!.notifyItemChanged(mAdapter!!.itemCount - 1)
+ }
+
+ if (mPinLockListener != null) {
+ if (mPin.length == mPinLength) {
+ mPinLockListener!!.onComplete(mPin)
+ } else {
+ mPinLockListener!!.onPinChange(mPin.length, mPin)
+ }
+ }
+ } else {
+ if (!isShowDeleteButton) {
+ resetPinLockView()
+ mPin += keyValue.toString()
+
+ if (isIndicatorDotsAttached) {
+ mIndicatorDots!!.updateDot(mPin.length)
+ }
+
+ if (mPinLockListener != null) {
+ mPinLockListener!!.onPinChange(mPin.length, mPin)
+ }
+
+ } else {
+ if (mPinLockListener != null) {
+ mPinLockListener!!.onComplete(mPin)
+ }
+ }
+ }
+ }
+ }
+
+ private val mOnDeleteClickListener = object : PinLockAdapter.OnDeleteClickListener {
+ override fun onDeleteClicked() {
+ if (mPin.isNotEmpty()) {
+ mPin = mPin.substring(0, mPin.length - 1)
+
+ if (isIndicatorDotsAttached) {
+ mIndicatorDots!!.updateDot(mPin.length)
+ }
+
+ if (mPin.isEmpty()) {
+ mAdapter!!.pinLength = mPin.length
+ mAdapter!!.notifyItemChanged(mAdapter!!.itemCount - 1)
+ }
+
+ if (mPinLockListener != null) {
+ if (mPin.isEmpty()) {
+ mPinLockListener!!.onEmpty()
+ clearInternalPin()
+ } else {
+ mPinLockListener!!.onPinChange(mPin.length, mPin)
+ }
+ }
+ } else {
+ if (mPinLockListener != null) {
+ mPinLockListener!!.onEmpty()
+ }
+ }
+ }
+
+ override fun onDeleteLongClicked() {
+ resetPinLockView()
+ if (mPinLockListener != null) {
+ mPinLockListener!!.onEmpty()
+ }
+ }
+ }
+
+ /**
+ * Get the length of the current pin length
+ *
+ * @return the length of the pin
+ */
+ /**
+ * Sets the pin length dynamically
+ *
+ * @param pinLength the pin length
+ */
+ var pinLength: Int
+ get() = mPinLength
+ set(pinLength) {
+ this.mPinLength = pinLength
+
+ if (isIndicatorDotsAttached) {
+ mIndicatorDots!!.pinLength = pinLength
+ }
+ }
+
+ /**
+ * Get the text color in the buttons
+ *
+ * @return the text color
+ */
+ /**
+ * Set the text color of the buttons dynamically
+ *
+ * @param textColor the text color
+ */
+ var textColor: Int
+ get() = mTextColor
+ set(textColor) {
+ this.mTextColor = textColor
+ mCustomizationOptionsBundle!!.textColor = textColor
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the size of the text in the buttons
+ *
+ * @return the size of the text in pixels
+ */
+ /**
+ * Set the size of text in pixels
+ *
+ * @param textSize the text size in pixels
+ */
+ var textSize: Int
+ get() = mTextSize
+ set(textSize) {
+ this.mTextSize = textSize
+ mCustomizationOptionsBundle!!.textSize = textSize
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the size of the pin buttons
+ *
+ * @return the size of the button in pixels
+ */
+ /**
+ * Set the size of the pin buttons dynamically
+ *
+ * @param buttonSize the button size
+ */
+ var buttonSize: Int
+ get() = mButtonSize
+ set(buttonSize) {
+ this.mButtonSize = buttonSize
+ mCustomizationOptionsBundle!!.buttonSize = buttonSize
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the current background drawable of the buttons, can be null
+ *
+ * @return the background drawable
+ */
+ /**
+ * Set the background drawable of the buttons dynamically
+ *
+ * @param buttonBackgroundDrawable the background drawable
+ */
+ var buttonBackgroundDrawable: Drawable?
+ get() = mButtonBackgroundDrawable
+ set(buttonBackgroundDrawable) {
+ this.mButtonBackgroundDrawable = buttonBackgroundDrawable
+ mCustomizationOptionsBundle!!.buttonBackgroundDrawable = buttonBackgroundDrawable
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the drawable of the delete button
+ *
+ * @return the delete button drawable
+ */
+ /**
+ * Set the drawable of the delete button dynamically
+ *
+ * @param deleteBackgroundDrawable the delete button drawable
+ */
+ var deleteButtonDrawable: Drawable?
+ get() = mDeleteButtonDrawable
+ set(deleteBackgroundDrawable) {
+ this.mDeleteButtonDrawable = deleteBackgroundDrawable
+ mCustomizationOptionsBundle!!.deleteButtonDrawable = deleteBackgroundDrawable
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the delete button size in pixels
+ *
+ * @return size in pixels
+ */
+ /**
+ * Set the size of the delete button in pixels
+ *
+ * @param deleteButtonSize size in pixels
+ */
+ var deleteButtonSize: Int
+ get() = mDeleteButtonSize
+ set(deleteButtonSize) {
+ this.mDeleteButtonSize = deleteButtonSize
+ mCustomizationOptionsBundle!!.deleteButtonSize = deleteButtonSize
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Is the delete button shown
+ *
+ * @return returns true if shown, false otherwise
+ */
+ /**
+ * Dynamically set if the delete button should be shown
+ *
+ * @param showDeleteButton true if the delete button should be shown, false otherwise
+ */
+ var isShowDeleteButton: Boolean
+ get() = mShowDeleteButton
+ set(showDeleteButton) {
+ this.mShowDeleteButton = showDeleteButton
+ mCustomizationOptionsBundle!!.isShowDeleteButton = showDeleteButton
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ /**
+ * Get the delete button pressed/focused state color
+ *
+ * @return color of the button
+ */
+ /**
+ * Set the pressed/focused state color of the delete button
+ *
+ * @param deleteButtonPressedColor the color of the delete button
+ */
+ var deleteButtonPressedColor: Int
+ get() = mDeleteButtonPressedColor
+ set(deleteButtonPressedColor) {
+ this.mDeleteButtonPressedColor = deleteButtonPressedColor
+ mCustomizationOptionsBundle!!.deleteButtonPressesColor = deleteButtonPressedColor
+ mAdapter!!.notifyDataSetChanged()
+ }
+
+ var customKeySet: IntArray?
+ get() = mCustomKeySet
+ set(customKeySet) {
+ this.mCustomKeySet = customKeySet
+
+ if (mAdapter != null) {
+ mAdapter!!.keyValues = customKeySet
+ }
+ }
+
+ /**
+ * Returns true if [IndicatorDots] are attached to [PinLockView]
+ *
+ * @return true if attached, false otherwise
+ */
+ val isIndicatorDotsAttached: Boolean
+ get() = mIndicatorDots != null
+
+ constructor(context: Context) : super(context) {
+ init(null, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
+ init(attrs, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) {
+ init(attrs, defStyle)
+ }
+
+ private fun init(attributeSet: AttributeSet?, defStyle: Int) {
+
+ val typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.PinLockView)
+
+ try {
+ mPinLength = typedArray.getInt(R.styleable.PinLockView_pinLength, DEFAULT_PIN_LENGTH)
+ mHorizontalSpacing = typedArray.getDimension(R.styleable.PinLockView_keypadHorizontalSpacing, ResourceUtils.getDimensionInPx(context, R.dimen.default_horizontal_spacing)).toInt()
+ mVerticalSpacing = typedArray.getDimension(R.styleable.PinLockView_keypadVerticalSpacing, ResourceUtils.getDimensionInPx(context, R.dimen.default_vertical_spacing)).toInt()
+ mTextColor = typedArray.getColor(R.styleable.PinLockView_keypadTextColor, ResourceUtils.getColor(context, R.color.white))
+ mTextSize = typedArray.getDimension(R.styleable.PinLockView_keypadTextSize, ResourceUtils.getDimensionInPx(context, R.dimen.default_text_size)).toInt()
+ mButtonSize = typedArray.getDimension(R.styleable.PinLockView_keypadButtonSize, ResourceUtils.getDimensionInPx(context, R.dimen.default_button_size)).toInt()
+ mDeleteButtonSize = typedArray.getDimension(R.styleable.PinLockView_keypadDeleteButtonSize, ResourceUtils.getDimensionInPx(context, R.dimen.default_delete_button_size)).toInt()
+ mButtonBackgroundDrawable = typedArray.getDrawable(R.styleable.PinLockView_keypadButtonBackgroundDrawable)
+ mDeleteButtonDrawable = typedArray.getDrawable(R.styleable.PinLockView_keypadDeleteButtonDrawable)
+ mShowDeleteButton = typedArray.getBoolean(R.styleable.PinLockView_keypadShowDeleteButton, true)
+ mDeleteButtonPressedColor = typedArray.getColor(R.styleable.PinLockView_keypadDeleteButtonPressedColor, ResourceUtils.getColor(context, R.color.greyish))
+ } finally {
+ typedArray.recycle()
+ }
+
+ mCustomizationOptionsBundle = CustomizationOptionsBundle()
+ mCustomizationOptionsBundle!!.textColor = mTextColor
+ mCustomizationOptionsBundle!!.textSize = mTextSize
+ mCustomizationOptionsBundle!!.buttonSize = mButtonSize
+ mCustomizationOptionsBundle!!.buttonBackgroundDrawable = mButtonBackgroundDrawable
+ mCustomizationOptionsBundle!!.deleteButtonDrawable = mDeleteButtonDrawable
+ mCustomizationOptionsBundle!!.deleteButtonSize = mDeleteButtonSize
+ mCustomizationOptionsBundle!!.isShowDeleteButton = mShowDeleteButton
+ mCustomizationOptionsBundle!!.deleteButtonPressesColor = mDeleteButtonPressedColor
+
+ initView()
+ }
+
+ private fun initView() {
+ layoutManager = LTRGridLayoutManager(context, 3)
+
+ mAdapter = PinLockAdapter(context)
+ mAdapter!!.onItemClickListener = mOnNumberClickListener
+ mAdapter!!.onDeleteClickListener = mOnDeleteClickListener
+ mAdapter!!.customizationOptions = mCustomizationOptionsBundle
+ adapter = mAdapter
+
+ addItemDecoration(ItemSpaceDecoration(mHorizontalSpacing, mVerticalSpacing, 3, false))
+ overScrollMode = View.OVER_SCROLL_NEVER
+ }
+
+ /**
+ * Sets a [PinLockListener] to the to listen to pin update events
+ *
+ * @param pinLockListener the listener
+ */
+ fun setPinLockListener(pinLockListener: PinLockListener) {
+ this.mPinLockListener = pinLockListener
+ }
+
+ fun enableLayoutShuffling() {
+ this.mCustomKeySet = ShuffleArrayUtils.shuffle(DEFAULT_KEY_SET)
+
+ if (mAdapter != null) {
+ mAdapter!!.keyValues = mCustomKeySet
+ }
+ }
+
+ private fun clearInternalPin() {
+ mPin = ""
+ }
+
+ /**
+ * Resets the [PinLockView], clearing the entered pin
+ * and resetting the [IndicatorDots] if attached
+ */
+ fun resetPinLockView() {
+
+ clearInternalPin()
+
+ mAdapter!!.pinLength = mPin.length
+ mAdapter!!.notifyItemChanged(mAdapter!!.itemCount - 1)
+
+ if (mIndicatorDots != null) {
+ mIndicatorDots!!.updateDot(mPin.length)
+ }
+ }
+
+ /**
+ * Attaches [IndicatorDots] to [PinLockView]
+ *
+ * @param mIndicatorDots the view to attach
+ */
+ fun attachIndicatorDots(mIndicatorDots: IndicatorDots) {
+ this.mIndicatorDots = mIndicatorDots
+ }
+
+ companion object {
+
+ private const val DEFAULT_PIN_LENGTH = 4
+ private val DEFAULT_KEY_SET = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.java b/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.java
deleted file mode 100644
index 57d7016b..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.andrognito.pinlockview;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.ColorRes;
-import android.support.annotation.DimenRes;
-import android.support.annotation.DrawableRes;
-import android.support.v4.content.ContextCompat;
-
-/**
- * Created by aritraroy on 10/06/16.
- */
-public class ResourceUtils {
-
- private ResourceUtils() {
- throw new AssertionError();
- }
-
- public static int getColor(Context context, @ColorRes int id) {
- return ContextCompat.getColor(context, id);
- }
-
- public static float getDimensionInPx(Context context, @DimenRes int id) {
- return context.getResources().getDimension(id);
- }
-
- public static Drawable getDrawable(Context context, @DrawableRes int id) {
- return ContextCompat.getDrawable(context, id);
- }
-}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.kt
new file mode 100644
index 00000000..b1b46d0b
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/ResourceUtils.kt
@@ -0,0 +1,34 @@
+package com.andrognito.pinlockview
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+
+import androidx.annotation.ColorRes
+import androidx.annotation.DimenRes
+import androidx.annotation.DrawableRes
+import androidx.core.content.ContextCompat
+
+/**
+ * Created by aritraroy on 10/06/16.
+ */
+class ResourceUtils private constructor() {
+
+ init {
+ throw AssertionError()
+ }
+
+ companion object {
+
+ fun getColor(context: Context, @ColorRes id: Int): Int {
+ return ContextCompat.getColor(context, id)
+ }
+
+ fun getDimensionInPx(context: Context, @DimenRes id: Int): Float {
+ return context.resources.getDimension(id)
+ }
+
+ fun getDrawable(context: Context, @DrawableRes id: Int): Drawable? {
+ return ContextCompat.getDrawable(context, id)
+ }
+ }
+}
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.java b/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.java
deleted file mode 100644
index 9475a946..00000000
--- a/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.andrognito.pinlockview;
-
-import java.util.Random;
-
-/**
- * Created by aritraroy on 10/03/17.
- */
-
-public class ShuffleArrayUtils {
-
- /**
- * Shuffle an array
- *
- * @param array
- */
- static int[] shuffle(int[] array) {
- int length = array.length;
- Random random = new Random();
- random.nextInt();
-
- for (int i = 0; i < length; i++) {
- int change = i + random.nextInt(length - i);
- swap(array, i, change);
- }
- return array;
- }
-
- private static void swap(int[] array, int index, int change) {
- int temp = array[index];
- array[index] = array[change];
- array[change] = temp;
- }
-}
\ No newline at end of file
diff --git a/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.kt b/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.kt
new file mode 100644
index 00000000..8bd96b7c
--- /dev/null
+++ b/pinlockview/src/main/java/com/andrognito/pinlockview/ShuffleArrayUtils.kt
@@ -0,0 +1,33 @@
+package com.andrognito.pinlockview
+
+import java.util.*
+
+/**
+ * Created by aritraroy on 10/03/17.
+ */
+
+object ShuffleArrayUtils {
+
+ /**
+ * Shuffle an array
+ *
+ * @param array
+ */
+ internal fun shuffle(array: IntArray): IntArray {
+ val length = array.size
+ val random = Random()
+ random.nextInt()
+
+ for (i in 0 until length) {
+ val change = i + random.nextInt(length - i)
+ swap(array, i, change)
+ }
+ return array
+ }
+
+ private fun swap(array: IntArray, index: Int, change: Int) {
+ val temp = array[index]
+ array[index] = array[change]
+ array[change] = temp
+ }
+}
\ No newline at end of file
diff --git a/pinlockview/src/main/res/anim/cycles_7.xml b/pinlockview/src/main/res/anim/cycles_7.xml
new file mode 100644
index 00000000..4bfb143a
--- /dev/null
+++ b/pinlockview/src/main/res/anim/cycles_7.xml
@@ -0,0 +1,3 @@
+
+
\ No newline at end of file
diff --git a/pinlockview/src/main/res/anim/shake_wrong.xml b/pinlockview/src/main/res/anim/shake_wrong.xml
new file mode 100644
index 00000000..26f89129
--- /dev/null
+++ b/pinlockview/src/main/res/anim/shake_wrong.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/pinlockview/src/main/res/drawable/dot_error.xml b/pinlockview/src/main/res/drawable/dot_error.xml
new file mode 100644
index 00000000..828f2df7
--- /dev/null
+++ b/pinlockview/src/main/res/drawable/dot_error.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/pinlockview/src/main/res/drawable/dot_success.xml b/pinlockview/src/main/res/drawable/dot_success.xml
new file mode 100644
index 00000000..a70f99a0
--- /dev/null
+++ b/pinlockview/src/main/res/drawable/dot_success.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/pinlockview/src/main/res/values/colors.xml b/pinlockview/src/main/res/values/colors.xml
index c04e047a..02275c64 100644
--- a/pinlockview/src/main/res/values/colors.xml
+++ b/pinlockview/src/main/res/values/colors.xml
@@ -1,6 +1,8 @@
#fff
- #aaa8a8
- #303030
+ #9E9C9C
+ #B40000
+ #50BD00
+ #333333
\ No newline at end of file