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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android自定义view之九宫格解锁

發(fā)布時間:2023/12/15 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android自定义view之九宫格解锁 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

android自定義view之九宮格解鎖

更多細節(jié)請看源碼
https://github.com/que123567/lockview

  • 1. 定義一個類作為九宮格的格子

    包含坐標和索引(用來記錄密碼)
    point含三種狀態(tài)分別對應三種不同情況下點的圖片樣式

package lockview;/*** Created by smaug on 2017/5/11.*/public class Point {public float x;public float y;private int index;public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}public static final int STATU_NORNAL = 0;public static final int STATU_PRESSED = 1;public static final int STATU_ERROR = 2;public int state;public void setState(int state) {this.state = state;}public int getState() {return state;}public Point() {super();}public Point(float x, float y) {this.x = x;this.y = y;}public float getX() {return x;}public void setX(float x) {this.x = x;}public float getY() {return y;}public void setY(float y) {this.y = y;} }
  • 2.新建類LockView繼承自View
    重寫onDraw()方法
    • 初始化點的時候根據(jù)獲取當前屏幕的寬高,比對來確定當前狀態(tài)是橫屏還是豎屏
    • 從資源中獲取Bitmap,將點設置成圖像。
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);initPoints();initPaint(); }private void drawPoints(Canvas canvas) {for (int i = 0; i < points.length; i++) {for (int j = 0; j < points[i].length; j++) {Point point = points[i][j];if (point.getState() == Point.STATU_NORNAL) {//獲取當前點的坐標,減去圖片的半徑得到left和top的坐標點canvas.drawBitmap(point_normal, point.x - br, point.y - br, null);} else if (point.getState() == Point.STATU_PRESSED) {canvas.drawBitmap(point_pressed, point.x - br, point.y - br, null);} else if (point.getState() == Point.STATU_ERROR) {canvas.drawBitmap(point_error, point.x - br, point.y - br, null);}}}}public class LockView extends View {private void initPoints() {width = getWidth();height = getHeight();if (height > width) {//豎屏offsetY = (height - width) / 2;height = width;} else { //橫屏offsetX = (height - width) / 2;width = height;}/*** 定義9個點的坐標*/points = new Point[row][colun];int index = 1;for (int i = 0; i < row; i++) {for (int j = 0; j < colun; j++) {points[i][j] = new Point(offsetX + (width / (row + 1)) * (i + 1), offsetY +(width / (colun + 1)) * (j + 1));points[i][j].setIndex(index);index++;}}/*** 從資源中獲取Bitmap*/point_normal = BitmapFactory.decodeResource(getResources(), R.drawable.point_normal);point_pressed = BitmapFactory.decodeResource(getResources(), R.drawable.point_pressed);point_error = BitmapFactory.decodeResource(getResources(), R.drawable.point_error);br = point_normal.getWidth() / 2;} }

顯示結果如下圖

  • 3.重寫onTouchEvent
case MotionEvent.ACTION_DOWN:reset();//先清空之前繪制的狀態(tài)checkedPoint = checkPoint(eventX, eventY, br);if (checkedPoint != null) {isSelecte = true;checkedPoint.setState(Point.STATU_PRESSED);}break;

checkPoint()通過計算坐標距離判斷當前手指坐標是否在point圖片上

private Point checkPoint(float eventX, float eventY, float br) {for (int i = 0; i < points.length; i++) {for (int j = 0; j < points[i].length; j++) {Point point = points[i][j];double distance = getDistance(point.x, point.y, eventX, eventY);if (distance < br) {return point;}}}return null;}

getDistance()利用勾股定理計算坐標距離

private double getDistance(float x, float y, float eventX, float eventY) {return Math.sqrt(Math.abs(x - eventX) * Math.abs(x - eventX) + Math.abs(y - eventY) *Math.abs(y - eventY));}

這個時候手指接觸都某個點,某個點的狀態(tài)就會從normal轉(zhuǎn)換為pressed,其對應的圖片也會改變。

  • 4.添加點與點之間的連線
    LockView中定義一個Point類的List —>pointList 記錄用戶按下的點

  • 當pointList為空,即用戶未按下任一點的時候不繪制線段,其余時刻都繪制

  • 繪制線段調(diào)用canvas的drawLine()方法,傳入起始點x,y坐標與目標點x,y坐標與一個自定義的paint畫筆繪制線段

private void drawLine(Canvas canvas) {if (pointList.size() > 0) {Point a = pointList.get(0);for (int i = 1; i < pointList.size(); i++) {Point b = pointList.get(i);canvas.drawLine(a.x, a.y, b.x, b.y, paint);a = b;}if (!moveOnPoint) { //canvas.drawLine(a.x, a.y, eventX, eventY, paint);}}}

效果如圖所示

  • 5.自動連接中間點

在九宮格中,如果用戶跳開中間點只連接了頭尾兩個點,按照規(guī)則應該把中間點自動連上。

即在ACTION_MOVE過程中始終判斷中間點是否被連入,而中間點的判斷方式為首尾點坐標/2.

case MotionEvent.ACTION_MOVE:if (isSelecte) {checkedPoint = checkPoint(eventX, eventY, br);if (checkedPoint != null) {if (!pointList.contains(checkedPoint)) {middlePoint = checkPoint((checkedPoint.x + lastPoint.x) / 2, (checkedPoint.y + lastPoint.y) / 2, br);if (middlePoint != null) {middlePoint.setState(Point.STATU_PRESSED);}}checkedPoint.setState(Point.STATU_PRESSED);moveOnPoint = true;} else {moveOnPoint = false;}}break;
  • 6.此外,在繪制過程中會記錄密碼,在使用該LockView時可設置setOnLockSuccessed監(jiān)聽來判斷,其中帶有參數(shù):正確密碼-passward

    對應的,連接數(shù)少于5判定為連接失敗,也有對應的監(jiān)聽事件。

if (pointList != null) {if (pointList.size() == 1) {reset();//重置} else if (pointList.size() < 5) {//個數(shù)不足errorPoint();//繪制錯誤的圖案if (onLockChangeListener != null) { //失敗onLockChangeListener.setOnLockError();}} else if (pointList.size() >= 5) { //九宮格連接數(shù)應大于等于5StringBuilder passward = new StringBuilder();for (int i = 0; i < pointList.size(); i++) {int tmpIndex = pointList.get(i).getIndex();passward.append(tmpIndex + "");}if (onLockChangeListener != null)//成功onLockChangeListener.setOnLockSuccessed(passward);}}

作者:邱鐘浩:原文地址

總結

以上是生活随笔為你收集整理的android自定义view之九宫格解锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。