把以前学过没学好的知识在这个demo中好好复习一下。这是我做的一个仿图形解锁。
总的来说分成三部分:
1.点的绘制
2.点的收集
3.线的绘制
效果图如下:
九宫格点的结构,包括x,y 坐标,三个状态量
public static class Point { public static int STATE_NORMAL = 0; public static int STATE_PRESSED = 1; public static int STATE_ERROR = 2; public float x, y; public int state = 0; public Point(float x, float y) { this.x = x; this.y = y; } }
一、点的绘制
首先我们要令九宫格都始终在屏幕中间,这要求我们要根据Layout的width,height来计算一个偏移量。每个点都与偏移量关联。
private void initPoint() { width = getWidth(); height = getHeight(); if (width > height) {//横屏 offsetX = (width - height) / 2;//计算偏移量,使Lock居中放置 width = height; } else {//竖屏 offsetY = (height - width) / 2;//计算偏移量,使Lock居中放置 height = width; } //各个点之间都间隔width/4,所以每个点的下标都是相差width/4 points[0][0] = new Point(offsetX + width / 4, offsetY + width / 4); points[0][1] = new Point(offsetX + width / 4, offsetY + width * 2 / 4); points[0][2] = new Point(offsetX + width / 4, offsetY + width * 3 / 4); points[1][0] = new Point(offsetX + width * 2 / 4, offsetY + width / 4); points[1][1] = new Point(offsetX + width * 2 / 4, offsetY + width * 2 / 4); points[1][2] = new Point(offsetX + width * 2 / 4, offsetY + width * 3 / 4); points[2][0] = new Point(offsetX + width * 3 / 4, offsetY + width / 4); points[2][1] = new Point(offsetX + width * 3 / 4, offsetY + width * 2 / 4); points[2][2] = new Point(offsetX + width * 3 / 4, offsetY + width * 3 / 4); isInit = true;//表示初始化完成 }
二、点的收集
我们在onTouch事件中进行判断。
public boolean onTouchEvent(MotionEvent event) { Point point = null; moveNoPoint = false; isFinish = false; moveX = event.getX(); moveY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: {//每次按下都是清空集合 resetPoint(); point = checkSelectedPoint(); if (point != null) { isSelect = true;//isSelect的作用就是,ACTION_DOWN时候一定要得到一个有效的起始点,手指移动时才会去收集点 } } break; case MotionEvent.ACTION_MOVE: { if (isSelect) {//如上面所说,有了起始点,才能陆续添加点 point = checkSelectedPoint(); if (point == null) { moveNoPoint = true;//moveNoPoint是用来判断是否有重复点, } } } break; case MotionEvent.ACTION_UP: {//抬手后,isFinish为true,isSelect也回到false以便下次连线使用 isFinish = true; isSelect = false; } break; } if (!isFinish && isSelect && point != null) {//选中重复检查 if (crossPoint(point)) {//重复点判断 moveNoPoint = true; } else {//新点 point.state = Point.STATE_PRESSED; pointPressed_list.add(point); } } if (isFinish) {//onTouch动作结束 if (pointPressed_list.size() == 1) {//绘制不成立 resetPoint(); } else if (pointPressed_list.size() < 5 && pointPressed_list.size() > 2) {//绘制错误,就是点的数量不正确 errorPoint(); } ; } //刷新 postInvalidate(); return true; }
三、线的绘制
对集合收集到的点进行绘制就好了
private void LineCanvas(Canvas canvas) {
if (pointPressed_list.size() == 0) {//集合中没点,不做处理
} else if (pointPressed_list.size() == 1) {//集合中只要1个点,不能连线,直接画线到触摸位置
if (isSelect == true) {
paint.setColor(Color.BLUE);
paint.setStrokeWidth(20);
Point point = pointPressed_list.get(0);
canvas.drawLine(point.x, point.y, moveX, moveY, paint);
}
} else {//分两种状态下画线,是否完成onTouch事件
if (!isFinish) {//onTouch还没结束的话,当集合中最后一个点不是第9个点,则集合最后一点连线到触摸位置
paint.setColor(Color.BLUE);
paint.setStrokeWidth(20);
if (pointPressed_list.size() == 1) {
Point point = pointPressed_list.get(0);
//取出当前点的X,Y
canvas.drawLine(point.x, point.y, moveX, moveY, paint);
} else {//不是最后一个点,两点之间正常连线
for (int i = 0; i < pointPressed_list.size() - 1; i++) {
Point pointPrevious = pointPressed_list.get(i);
Point pointNext = pointPressed_list.get(i + 1);
lastX = pointNext.x;
lastY = pointNext.y;
canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNext.x, pointNext.y, paint);
}
if (pointPressed_list.size() < 9) {//当然啦,9个点全画了的话,就不用连线触摸点了
canvas.drawLine(lastX, lastY, moveX, moveY, paint);
}
}
} else if (isFinish) {//onTouch事件结束后,就重画所有连线,其中再判断下点的状态是否ERROR
paint.setColor(Color.BLUE);
paint.setStrokeWidth(20);
for (int i = 0; i < pointPressed_list.size() - 1; i++) {
Point pointPrevious = pointPressed_list.get(i);
Point pointNext = pointPressed_list.get(i + 1);
if (pointPrevious.state == Point.STATE_ERROR) {
paint.setColor(Color.RED);
}
canvas.drawLine(pointPrevious.x, pointPrevious.y, pointNext.x, pointNext.y, paint);
}
}
}
}
GitHub地址:
MyLock源码下载