Android開發筆記[13]-圖案密碼

qsBye發表於2024-03-17

摘要

輸入圖案密碼123跳轉到關於頁面.

關鍵資訊

  • Android Studio:Iguana | 2023.2.1
  • Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-8.4-bin.zip
  • jvmTarget = '1.8'
  • minSdk 21
  • targetSdk 34
  • compileSdk 34
  • 開發語言:Kotlin,Java
  • ndkVersion = '21.1.6352462'
  • kotlin版本:1.9.20
  • kotlinCompilerExtensionVersion '1.5.4'
  • com.android.library:8.3

原理簡介

圖案密碼

[https://gitcode.com/aritraroy/patternlockview/overview]
[https://github.com/aritraroy/PatternLockView]
[https://blog.csdn.net/shenggaofei/article/details/100054501]
[https://blog.csdn.net/qq_36243942/article/details/104186126]
[https://blog.csdn.net/Joson_Wang/article/details/49929775]
[https://blog.csdn.net/octopusflying/article/details/80157204]
Android 的圖案密碼解鎖,透過手勢連線 3 * 3 的點矩陣繪製圖案表示解鎖密碼,對應一定順序的數字序列。
圖案方式比較直觀,具有易於記憶的特點。
圖案密碼的工作原理是將裝置的螢幕劃分為一系列的點或區域,使用者需要按照特定的順序在這些點或區域內滑動手指,從而形成一種獨特的圖案。這種圖案就像一個密碼一樣,只有知道正確的圖案才能解鎖裝置。
圖案密碼具有較高的安全性,因為它們可以組合成大量的不同圖案。同時,由於圖案密碼直觀易用,因此也受到了許多使用者的歡迎。

圖案密碼示例

實現

核心程式碼

  1. 修改build.gradle
/* start 圖案密碼庫相關 */
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
implementation 'com.andrognito.patternlockview:patternlockview-reactive:1.0.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.1.4'
/* end 圖案密碼庫相關 */
  1. 新增PatternLockActivity頁面
    AndroidManifest.xml
<!-- 圖案密碼頁 -->
<activity
    android:name=".PatternLockViewActivity"
    android:exported="false"
    android:label="@string/title_activity_pattern_lock_view"
    android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />

activity_pattern_lock.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/matisse_capture_icon_color"
    android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/profile_image"
        android:layout_width="84dp"
        android:layout_height="84dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="50dp"
        android:src="@drawable/weekend_android_logo"/>

    <TextView
        android:id="@+id/profile_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="36dp"
        android:fontFamily="sans-serif-thin"
        android:gravity="center"
        android:maxLines="1"
        android:text="請輸入頁面跳轉碼(試一試123)"
        android:textColor="@color/white"
        android:textSize="20sp"/>

    <com.andrognito.patternlockview.PatternLockView
        android:id="@+id/pattern_lock_view"
        android:layout_width="280dp"
        android:layout_height="280dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="16dp"
        app:aspectRatio="square"
        app:aspectRatioEnabled="true"
        app:dotAnimationDuration="150"
        app:dotCount="3"
        app:normalStateColor="@color/white"
        app:correctStateColor="@color/macaron_raspberry_cheesecake"
        app:wrongStateColor="@color/pomegranate"
        app:dotSelectedSize="50dp"
        />

    <!--    自定義屬性-->
    <!--     app:dotCount="3"                                        // 更改行(或列)-->
    <!--    app:dotNormalSize="12dp"                                // 更改正常狀態-->
    <!--    app:dotSelectedSize="24dp"                              // 更改選定狀態-->
    <!--    app:pathWidth="4dp"                                     // 更改路徑-->
    <!--    app:aspectRatioEnabled="true"                           // 設定檢視是否應該遵循自定義寬高比-->
    <!--    app:aspectRatio="square"                                // 設定在“square”,“width_bias”,“height_bias”-->
    <!--    app:normalStateColor="@color/white"                     // 設定正常狀態下圖案檢視的顏色-->
    <!--    app:correctStateColor="@color/primary"                  // 將圖案檢視的顏色設定為正確狀態-->
    <!--    app:wrongStateColor="@color/pomegranate"                // 設定錯誤狀態-->
    <!--    app:dotAnimationDuration="200"                          // 更改動畫點-->
    <!--    app:pathEndAnimationDuration="100"                      // 更改路徑結束動畫的持續時間-->

</LinearLayout>

PatternLockActivity.kt

package cn.qsbye.weekend_android

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.widget.TextView
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import cn.qsbye.weekend_android.AboutPageClass.MyViewModel
import cn.qsbye.weekend_android.ui.theme.WeekendAndroidTheme
import io.noties.markwon.Markwon
import com.andrognito.patternlockview.PatternLockView
import com.andrognito.patternlockview.listener.PatternLockViewListener
import com.andrognito.patternlockview.utils.PatternLockUtils
import com.andrognito.patternlockview.utils.ResourceUtils
import com.andrognito.rxpatternlockview.RxPatternLockView
import com.andrognito.rxpatternlockview.events.PatternLockCompleteEvent
import com.andrognito.rxpatternlockview.events.PatternLockCompoundEvent
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.functions.Consumer

class PatternLockViewActivity : ComponentActivity() {

    // 圖案密碼
    private lateinit var myPatternLock: MyPatternLock

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            WeekendAndroidTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    // 顯示圖案密碼
                    myPatternLock = MyPatternLock(this@PatternLockViewActivity)
                    myPatternLock.initPatternLockView()
                }
            }
        }
    } // end onCreate

}

/* start 頁面佈局 */

class MyPatternLock(private val context: Activity) {
    // 圖案密碼
    private lateinit var mPatternLockView: PatternLockView

    @Composable
    fun initPatternLockView() {
        Column(
            Modifier
                .fillMaxSize()
                .background(Color.White)
        ) {

            /* start XML佈局 */
            AndroidView(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                factory = { ctx ->
                    val layout_from_xml =
                        LayoutInflater.from(ctx).inflate(R.layout.activity_pattern_lock, null)
                    mPatternLockView = layout_from_xml.findViewById(R.id.pattern_lock_view)
                    // 繫結圖案密碼回撥
                    mPatternLockView.addPatternLockListener(mPatternLockViewListener)
                    layout_from_xml // Return the TextView instance
                },
            )

            /* end XML佈局 */
        }
    }

    /* start 回撥監聽事件 */
    private val mPatternLockViewListener = object : PatternLockViewListener {
        override fun onStarted() {
            Log.d(context::class.simpleName, "Pattern drawing started")
        }

        override fun onProgress(progressPattern: List<PatternLockView.Dot>) {
            Log.d(
                context::class.simpleName, "Pattern progress: " +
                        PatternLockUtils.patternToString(mPatternLockView, progressPattern)
            )
        }

        override fun onComplete(pattern: List<PatternLockView.Dot>) {
            Log.d(
                context::class.simpleName, "Pattern complete: " +
                        PatternLockUtils.patternToString(mPatternLockView, pattern)
            )
            val password_to_about_activity = "123"
            val patternToString = PatternLockUtils.patternToString(mPatternLockView, pattern)
            if (!TextUtils.isEmpty(patternToString)) {
                if (patternToString == password_to_about_activity) {
                    Toast.makeText(
                        context, "您繪製的密碼是:$patternToString\n" +
                                "密碼正確,正在進入關於頁...", Toast.LENGTH_SHORT
                    ).show()
                    val intent = Intent(context, AboutActivity::class.java)
                    context.startActivity(intent)
                    context.finish()
                } else {
                    Toast.makeText(
                        context, "您繪製的密碼是:$patternToString\n" +
                                "密碼錯誤,請重新繪製", Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }

        override fun onCleared() {
            Log.d(context::class.simpleName, "Pattern has been cleared")
        }
    }
    /* end 回撥監聽事件 */
}
/* end 頁面佈局 */

效果

輸入圖案密碼進入相應頁面

相關文章