android自定義view之九宮格解鎖
更多細節(jié)請看源碼
https://github.com/que123567/lockview
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) {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;}
}
顯示結果如下圖
case MotionEvent.ACTION_DOWN:reset();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轉換為pressed,其對應的圖片也會改變。
4.添加點與點之間的連線
LockView中定義一個Point類的List —>pointList 記錄用戶按下的點
當pointList為空,即用戶未按下任一點的時候不繪制線段,其余時刻都繪制
繪制線段調用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);}}}
效果如圖所示
在九宮格中,如果用戶跳開中間點只連接了頭尾兩個點,按照規(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;
if (pointList !=
null) {
if (pointList.size() ==
1) {reset();}
else if (pointList.size() <
5) {errorPoint();
if (onLockChangeListener !=
null) { onLockChangeListener.setOnLockError();}}
else if (pointList.size() >=
5) { StringBuilder 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之九宫格解锁的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。