日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android自定义九宫格手势解锁组件

發布時間:2023/12/15 Android 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android自定义九宫格手势解锁组件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

項目來源

別的不說,先看一下效果圖:

九宮格手勢圖案解鎖功能在很多應用中都在使用,本文介紹的組件來自于開源項目PatternLocker的翻寫,原工程是使用Kotlin開發的,由于我們項目是使用java開發,所以將原工程使用Java進行了翻寫,如果需要kotlin版本的請移步原工程Kotlin版九宮格手勢解鎖組件,如果需要Java版本的可以點此下載Java版九宮格手勢解鎖組件。本文主要介紹Java版本九宮格手勢解鎖組件的使用和實現原理。

支持功能

  • 支持自定義各狀態下(未操作時、操作時以及操作出錯時)線顏色、填充色和線寬;
  • 支持自定義各種狀態下(未操作時、操作時以及操作出錯時)每個CellView樣式和連接線樣式;
  • 支持設置圖案繪制完成后延遲自動清除的時長(默認1秒);
  • 支持是否跳過中間點(默認不跳過);
  • 支持是否觸碰震動反饋(默認不震動);
  • 支持指示器輔助控件可選擇使用;
  • 業務邏輯(至少連點幾個點、驗證時最多可出錯幾次等)須自定義

九宮格實現原理

1、九宮格由9個格子組成,首先給每個格子分配id,9個cell的編號如下:
0 1 2
3 4 5
6 7 8

2、給每個格子設置坐標
x 表示該cell的x坐標(點坐標)
y 表示該cell的y坐標(點坐標)
九宮格每個格子x,y 點坐標編號如下:
(0,0) (1,0) (2,0)
(0,1) (1,1) (2,1)
(0,2) (1,2) (2,2)

3、每個格子就是一個圓,所以需要圓心坐標和半徑,格子圓心之間距離為3個半徑,
centerX 表示該cell的圓心x坐標(相對坐標)
centerY 表示該cell的圓心y坐標(相對坐標)
centerX, centerY 圓心坐標如下:
(radius, radius) (4radius, radius) (7radius, radius)
(radius, 4radius) (4radius, 4radius) (7radius, 4radius)
(radius, 7radius) (4radius, 7radius) (7radius, 7radius)

4、每個格子需要標記是否被選中狀態
isHit 表示該cell是否被設置的標記

工程源碼介紹

采用自定義View的形式,組件分為兩部分,第一部分是指示器View,第二部分是九宮格繪制View。
指示器View:

<com.github.gesture.lockview.PatternIndicatorViewandroid:id="@+id/patternIndicatorView"android:layout_width="50dp"android:layout_height="50dp"android:layout_margin="20dp"/>

九宮格View:

<com.github.gesture.lockview.PatternLockerViewandroid:id="@+id/patternLockerView"android:layout_width="250dp"android:layout_height="250dp" />

這兩個view可以拆開使用,如果不需要指示器,就只集成九宮格View即可。由于指示器View和九宮格View邏輯差不多,這里只簡單分析一下九宮格View的實現代碼。

九宮格View相關類:
PatternLockerView:九宮格View實現類;
DefaultLockerNormalCellView:默認九宮格每一個格子實現類;
DefaultLockerLinkedLineView:默認九宮格連線實現類;
DefaultLockerHitCellView:默認九宮格選中后格子樣式實現類;

PatternLockerView

該類主要初始化九宮格9個格子實體,并且重寫onDraw和 onMeasure方法,

初始化init方法主要讀取attr中的配置屬性;
onMeasure方法中選擇寬和高的最小值設為View的寬高。
onDraw方法:

@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);// 初始化九宮格每個格子實例this.initCellBeanList();// 畫線this.drawLinkedLine(canvas);// 畫每個格子this.drawCells(canvas); }

drawLinkedLine方法調用的是DefaultLockerLinkedLineView中畫線方法;
drawCells方法調用的是DefaultLockerNormalCellView中畫格子方法;

下面分別分析一下如何畫格子和畫連接線的。

DefaultLockerNormalCellView

畫格子方法如下,先畫個外圓,然后再畫個內圓。

public void draw(Canvas canvas, CellBean cellBean) {int saveCount = canvas.save();// draw outer circlethis.paint.setColor(this.styleDecorator.getNormalColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius(), this.paint);// draw fill circlethis.paint.setColor(this.styleDecorator.getFillColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() - this.styleDecorator.getLineWidth(), this.paint);canvas.restoreToCount(saveCount);}

DefaultLockerHitCellView

繪制選中的格子是先畫外圓,再畫填充圓,最后畫內圓,只是顏色不一樣。

@Overridepublic void draw(Canvas canvas, CellBean cellBean, boolean isError) {int saveCount = canvas.save();// draw outer circle 畫外圓this.paint.setColor(this.getColor(isError));canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius(), this.paint);// draw fill circle 畫填充圓this.paint.setColor(this.styleDecorator.getFillColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() - this.styleDecorator.getLineWidth(), this.paint);// draw inner circle 畫內部圓this.paint.setColor(this.getColor(isError));canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() / 5f, this.paint);canvas.restoreToCount(saveCount);}

DefaultLockerLinkedLineView

畫線方法有點復雜,是通過遍歷選中的格子id的集合,使用Path的moveTo移動線坐標,使用lineTo來連線,最后調用drawPath畫出線條。

public void draw(Canvas canvas, List<Integer> hitIndexList, List<CellBean> cellBeanList, float endX, float endY, boolean isError) {if (hitIndexList.isEmpty() || cellBeanList.isEmpty()) {return;}int saveCount = canvas.save();Path path = new Path();boolean first = true;for (int i = 0; i < hitIndexList.size(); i++) {// 記錄選中的點idInteger it = hitIndexList.get(i);if (0 <= it && it < cellBeanList.size()) {// 獲取選中的點CellBean c = cellBeanList.get(it);if (first) {path.reset();// 如果是第一個,則先將起點移動到第一個點path.moveTo(c.getCenterX(), c.getCenterY());first = false;} else {// 連接第一個點到第二個點path.lineTo(c.getCenterX(), c.getCenterY());}}}if ((endX != 0f || endY != 0f) && hitIndexList.size() < 9) {path.lineTo(endX, endY);}this.paint.setColor(this.getColor(isError));this.paint.setStrokeWidth(this.styleDecorator.getLineWidth());canvas.drawPath(path, this.paint);canvas.restoreToCount(saveCount);}

onTouchEvent

主要邏輯實現在onTouchEvent方法中,分別處理手勢按下、滑動、抬起狀態時的邏輯。處理完邏輯都會調用重繪方法,然后觸發onDraw方法,再次執行繪制過程。

按下、滑動、抬起時都會調用updateHitState方法,在updateHitState方法中通過一個List集合來記錄被選中的格子的id,繪制的時候再根據該集合更新格子狀態。

文章只是粗略介紹一下九宮格手勢圖案解鎖組件的實現原理和過程,深入研究還需要把源碼下載下來看一下。

源碼下載:

Kotlin版九宮格手勢解鎖組件
Java版九宮格手勢解鎖組件

總結

以上是生活随笔為你收集整理的Android自定义九宫格手势解锁组件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。