diff --git a/app/build.gradle b/app/build.gradle index 2e2d014..6b2adcb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,8 +35,8 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) -// implementation project(':library') - implementation "com.github.ihsg:PatternLocker:$rootProject.ext.versionName" + implementation project(':library') +// implementation "com.github.ihsg:PatternLocker:$rootProject.ext.versionName" implementation "androidx.appcompat:appcompat:$rootProject.ext.appcompatVersion" implementation "androidx.core:core-ktx:$rootProject.ext.coreKtxVersion" diff --git a/app/src/main/java/com/github/ihsg/demo/ui/whole/RippleLockerHitCellView.kt b/app/src/main/java/com/github/ihsg/demo/ui/whole/RippleLockerHitCellView.kt index 4046039..a9156c5 100644 --- a/app/src/main/java/com/github/ihsg/demo/ui/whole/RippleLockerHitCellView.kt +++ b/app/src/main/java/com/github/ihsg/demo/ui/whole/RippleLockerHitCellView.kt @@ -52,13 +52,13 @@ class RippleLockerHitCellView : IHitCellView { val saveCount = canvas.save() this.paint.color = getColor(isError) and 0x14FFFFFF - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius, this.paint) this.paint.color = getColor(isError) and 0x43FFFFFF - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius * 2f / 3f, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius * 2f / 3f, this.paint) this.paint.color = getColor(isError) - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius / 3f, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius / 3f, this.paint) canvas.restoreToCount(saveCount) } diff --git a/build.gradle b/build.gradle index f6a1078..3014016 100644 --- a/build.gradle +++ b/build.gradle @@ -3,18 +3,18 @@ buildscript { // versions ext { - versionCode = 20 - versionName = '2.5.6' + versionCode = 21 + versionName = '2.5.7' minSdkVersion = 15 targetSdkVersion = 29 compileSdkVersion = 29 buildToolsVersion = '29.0.3' - appcompatVersion = '1.1.0' - coreKtxVersion = '1.2.0' + appcompatVersion = '1.2.0' + coreKtxVersion = '1.3.2' constraintLayoutVersion = '1.1.3' - kotlinVersion = '1.3.71' + kotlinVersion = '1.4.21' } repositories { @@ -23,7 +23,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 465b5c6..c95d0bd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Apr 19 11:09:52 CST 2019 +#Tue Dec 29 15:08:36 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/library/src/main/java/com/github/ihsg/patternlocker/CellBean.kt b/library/src/main/java/com/github/ihsg/patternlocker/CellBean.kt index 04d2f79..317ab36 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/CellBean.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/CellBean.kt @@ -11,12 +11,30 @@ import kotlin.math.sqrt * 3 4 5 * 6 7 8 * - * @param x 表示该cell的x坐标(相对坐标) - * @param y 表示该cell的y坐标(相对坐标) + * @param x 表示该cell的x坐标(点坐标) + * @param y 表示该cell的y坐标(点坐标) + * x,y 点坐标编号如下: + * (0,0) (1,0) (2,0) + * (0,1) (1,1) (2,1) + * (0,2) (1,2) (2,2) + * + * @param centerX 表示该cell的圆心x坐标(相对坐标) + * @param centerY 表示该cell的圆心y坐标(相对坐标) + * centerX, centerY 圆心坐标如下: + * (radius, radius) (4radius, radius) (7radius, radius) + * (radius, 4radius) (4radius, 4radius) (7radius, 4radius) + * (radius, 7radius) (4radius, 7radius) (7radius, 7radius) + * * @param radius 表示该cell的半径 * @param isHit 表示该cell是否被设置的标记 */ -data class CellBean(val id: Int, val x: Float, val y: Float, val radius: Float, var isHit: Boolean = false) { +data class CellBean(val id: Int, + val x: Int, + val y: Int, + val centerX: Float, + val centerY: Float, + val radius: Float, + var isHit: Boolean = false) { /** * 是否触碰到该view * @@ -24,10 +42,9 @@ data class CellBean(val id: Int, val x: Float, val y: Float, val radius: Float, * @param y * @return */ - fun of(x: Float, y: Float, enableSkip: Boolean): Boolean { - val dx = this.x - x - val dy = this.y - y - val r = if (enableSkip) this.radius else this.radius * 1.5f - return sqrt((dx * dx + dy * dy).toDouble()) <= r.toDouble() + fun of(x: Float, y: Float): Boolean { + val dx = this.centerX - x + val dy = this.centerY - y + return sqrt((dx * dx + dy * dy)).toDouble() <= this.radius.toDouble() } } \ No newline at end of file diff --git a/library/src/main/java/com/github/ihsg/patternlocker/CellFactory.kt b/library/src/main/java/com/github/ihsg/patternlocker/CellFactory.kt index 23de5d3..7d6bc53 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/CellFactory.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/CellFactory.kt @@ -4,23 +4,24 @@ package com.github.ihsg.patternlocker * Created by hsg on 20/09/2017. */ -internal class CellFactory(private val width: Int, private val height: Int) { - val cellBeanList: List by lazy { - val result = ArrayList() - result.clear() +object CellFactory { - val pWidth = this.width / 8f - val pHeight = this.height / 8f + fun buildCells(width: Int, height: Int): List { + val result = ArrayList() + val pWidth = width / 8f + val pHeight = height / 8f - for (i: Int in 0..2) { - for (j: Int in 0..2) { - val id = (i * 3 + j) % 9 - val x = (j * 3 + 1) * pWidth - val y = (i * 3 + 1) * pHeight - result.add(CellBean(id, x, y, pWidth)) - } + for (i in 0..8) { + result.add(CellBean(i, + i % 3, + i / 3, + (i % 3 * 3 + 1) * pWidth, + (i / 3 * 3 + 1) * pHeight, + pWidth)) } + Logger.d("CellFactory", "result = $result") - return@lazy result + + return result } } \ No newline at end of file diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultConfig.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultConfig.kt index 44bc88d..af45be4 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultConfig.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultConfig.kt @@ -47,7 +47,7 @@ internal object DefaultConfig { return paint } - private fun convertDpToPx(dp: Float, resources: Resources): Float { - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics) + private fun convertDpToPx(dpValue: Float, resources: Resources): Float { + return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, resources.displayMetrics) } } \ No newline at end of file diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorHitCellView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorHitCellView.kt index 4501cd6..3255aca 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorHitCellView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorHitCellView.kt @@ -22,7 +22,7 @@ open class DefaultIndicatorHitCellView(val styleDecorator: DefaultStyleDecorator val saveCount = canvas.save() this.paint.color = this.getColor(isError) - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius, this.paint) canvas.restoreToCount(saveCount) } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorLinkedLineView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorLinkedLineView.kt index 192747a..d7c10b0 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorLinkedLineView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorLinkedLineView.kt @@ -32,10 +32,10 @@ open class DefaultIndicatorLinkedLineView(val styleDecorator: DefaultStyleDecora if (0 <= it && it < cellBeanList.size) { val c = cellBeanList[it] if (first) { - path.moveTo(c.x, c.y) + path.moveTo(c.centerX, c.centerY) first = false } else { - path.lineTo(c.x, c.y) + path.lineTo(c.centerX, c.centerY) } } } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorNormalCellView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorNormalCellView.kt index e289aea..ceb54a9 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorNormalCellView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultIndicatorNormalCellView.kt @@ -22,11 +22,11 @@ open class DefaultIndicatorNormalCellView(val styleDecorator: DefaultStyleDecora //outer circle this.paint.color = this.styleDecorator.normalColor - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius, this.paint) //inner circle this.paint.color = this.styleDecorator.fillColor - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius - this.styleDecorator.lineWidth, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius - this.styleDecorator.lineWidth, this.paint) canvas.restoreToCount(saveCount) } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerHitCellView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerHitCellView.kt index 894cc7e..d578f4e 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerHitCellView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerHitCellView.kt @@ -23,15 +23,15 @@ open class DefaultLockerHitCellView(val styleDecorator: DefaultStyleDecorator) : // draw outer circle this.paint.color = this.getColor(isError) - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius, this.paint) // draw fill circle this.paint.color = this.styleDecorator.fillColor - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius - this.styleDecorator.lineWidth, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius - this.styleDecorator.lineWidth, this.paint) // draw inner circle this.paint.color = this.getColor(isError) - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius / 5f, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius / 5f, this.paint) canvas.restoreToCount(saveCount) } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerLinkedLineView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerLinkedLineView.kt index 8ed16e0..41df1db 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerLinkedLineView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerLinkedLineView.kt @@ -36,10 +36,10 @@ open class DefaultLockerLinkedLineView(val styleDecorator: DefaultStyleDecorator if (0 <= it && it < cellBeanList.size) { val c = cellBeanList[it] if (first) { - path.moveTo(c.x, c.y) + path.moveTo(c.centerX, c.centerY) first = false } else { - path.lineTo(c.x, c.y) + path.lineTo(c.centerX, c.centerY) } } } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerNormalCellView.kt b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerNormalCellView.kt index e05e00a..589381e 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerNormalCellView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/DefaultLockerNormalCellView.kt @@ -21,11 +21,11 @@ open class DefaultLockerNormalCellView(val styleDecorator: DefaultStyleDecorator // draw outer circle this.paint.color = this.styleDecorator.normalColor - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius, this.paint) // draw fill circle this.paint.color = this.styleDecorator.fillColor - canvas.drawCircle(cellBean.x, cellBean.y, cellBean.radius - this.styleDecorator.lineWidth, this.paint) + canvas.drawCircle(cellBean.centerX, cellBean.centerY, cellBean.radius - this.styleDecorator.lineWidth, this.paint) canvas.restoreToCount(saveCount) } diff --git a/library/src/main/java/com/github/ihsg/patternlocker/PatternIndicatorView.kt b/library/src/main/java/com/github/ihsg/patternlocker/PatternIndicatorView.kt index 958660c..66e742b 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/PatternIndicatorView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/PatternIndicatorView.kt @@ -20,13 +20,11 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr var hitCellView: IHitCellView? = null private var isError: Boolean = false - private val hitIndexList: MutableList by lazy { - mutableListOf() - } + private var hitIndexList = emptyList() private val cellBeanList: List by lazy { val w = this.width - this.paddingLeft - this.paddingRight val h = this.height - this.paddingTop - this.paddingBottom - CellFactory(w, h).cellBeanList + CellFactory.buildCells(w, h) } init { @@ -34,20 +32,8 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr } fun updateState(hitIndexList: List?, isError: Boolean) { - //1. clear pre state - if (this.hitIndexList.isNotEmpty()) { - this.hitIndexList.clear() - } - - //2. record new state - hitIndexList?.let { - this.hitIndexList.addAll(it) - } - - //3. update result + this.hitIndexList = hitIndexList ?: emptyList() this.isError = isError - - //4. update view invalidate() } @@ -64,7 +50,6 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr private fun init(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { this.initAttrs(context, attrs, defStyleAttr) - this.initData() } private fun initAttrs(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { @@ -84,10 +69,6 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr this.linkedLineView = DefaultIndicatorLinkedLineView(decorator) } - private fun initData() { - this.hitIndexList.clear() - } - private fun updateHitState() { //1. clear pre state this.cellBeanList.forEach { @@ -95,13 +76,9 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr } //2. update hit state - this.hitIndexList.let { it -> - if (it.isNotEmpty()) { - it.forEach { - if (0 <= it && it < this.cellBeanList.size) { - this.cellBeanList[it].isHit = true - } - } + this.hitIndexList.forEach { + if (0 <= it && it < this.cellBeanList.size) { + this.cellBeanList[it].isHit = true } } } @@ -109,15 +86,15 @@ open class PatternIndicatorView @JvmOverloads constructor(context: Context, attr private fun drawLinkedLine(canvas: Canvas) { if (this.hitIndexList.isNotEmpty()) { this.linkedLineView?.draw(canvas, - this.hitIndexList, - this.cellBeanList, - this.isError) + this.hitIndexList, + this.cellBeanList, + this.isError) } } private fun drawCells(canvas: Canvas) { this.cellBeanList.forEach { - if (it.isHit && this.hitCellView != null) { + if (it.isHit) { this.hitCellView?.draw(canvas, it, this.isError) } else { this.normalCellView?.draw(canvas, it) diff --git a/library/src/main/java/com/github/ihsg/patternlocker/PatternLockerView.kt b/library/src/main/java/com/github/ihsg/patternlocker/PatternLockerView.kt index 854428e..80c9f53 100644 --- a/library/src/main/java/com/github/ihsg/patternlocker/PatternLockerView.kt +++ b/library/src/main/java/com/github/ihsg/patternlocker/PatternLockerView.kt @@ -6,6 +6,7 @@ import android.util.AttributeSet import android.view.HapticFeedbackConstants import android.view.MotionEvent import android.view.View +import kotlin.math.abs import kotlin.math.min @@ -79,7 +80,7 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: private lateinit var cellBeanList: List /** - * 记录已绘制的cell的id + * 记录已绘制cell的id */ private val hitIndexList: MutableList by lazy { mutableListOf() @@ -95,7 +96,6 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: this.initData() } - fun enableDebug() { Logger.enable = true } @@ -118,9 +118,7 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: fun clearHitState() { this.clearHitData() this.isError = false - if (this.listener != null) { - this.listener!!.onClear(this) - } + this.listener?.onClear(this) invalidate() } @@ -194,18 +192,18 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: if (!this::cellBeanList.isInitialized) { val w = this.width - this.paddingLeft - this.paddingRight val h = this.height - this.paddingTop - this.paddingBottom - this.cellBeanList = CellFactory(w, h).cellBeanList + this.cellBeanList = CellFactory.buildCells(w, h) } } private fun drawLinkedLine(canvas: Canvas) { if (this.hitIndexList.isNotEmpty()) { this.linkedLineView?.draw(canvas, - this.hitIndexList, - this.cellBeanList, - this.endX, - this.endY, - this.isError) + this.hitIndexList, + this.cellBeanList, + this.endX, + this.endY, + this.isError) } } @@ -270,7 +268,15 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: private fun updateHitState(event: MotionEvent) { this.cellBeanList.forEach { - if (!it.isHit && it.of(event.x, event.y, this.enableSkip)) { + if (!it.isHit && it.of(event.x, event.y)) { + if (!enableSkip && this.hitIndexList.isNotEmpty()) { + val last = this.cellBeanList[this.hitIndexList.last()] + val mayId = (last.id + it.id) / 2 + if (!this.hitIndexList.contains(mayId) && (abs(last.x - it.x) % 2 == 0) && (abs(last.y - it.y) % 2 == 0)) { + this.cellBeanList[mayId].isHit = true + this.hitIndexList.add(mayId) + } + } it.isHit = true this.hitIndexList.add(it.id) this.hapticFeedback() @@ -305,8 +311,8 @@ open class PatternLockerView @JvmOverloads constructor(context: Context, attrs: private fun hapticFeedback() { if (this.enableHapticFeedback) { this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING - or HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING + or HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) } }