1. 程式人生 > >Android中圖案解鎖的設計原理和實現過程

Android中圖案解鎖的設計原理和實現過程

<span style="font-size:14px;">package com.example.patternlock;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class LockView extends View {
	private boolean inited = false;
	Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 抗鋸齒
	Paint pressPaint = new Paint(); //按下時的畫筆
	Paint errorPaint = new Paint(); //錯誤時的畫筆
	private Bitmap bitmapPointError;
	private Bitmap bitmapPointPress;
	private Bitmap bitmapPointNormal;
	private float bitmapR; // 點的半徑
	private boolean isDraw = false; //是否正在繪製
	float mouseX, mouseY;
	private Point [][] points = new Point[3][3];
	private ArrayList<Point> pointList = new ArrayList<Point>(); //儲存經過的點
	private ArrayList<Integer> passList = new ArrayList<Integer>();
	private OnDrawFinishedListener listener;

	public LockView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
	}

	public LockView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public LockView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		mouseX = event.getX();
		mouseY = event.getY();
		int [] ij;
		int i , j;
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			resetPoints();
			ij = getSelectedPoint();
			if(ij != null){
				isDraw = true;
				i = ij[0];
				j = ij[1];
				points[i][j].state = Point.STATE_PRESS;
				pointList.add(points[i][j]);
				passList.add(i * 3 + j);
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if(isDraw){
				ij = getSelectedPoint();
				if(ij != null){
					i = ij[0];
					j = ij[1];
					if(!pointList.contains(points[i][j])){
						points[i][j].state = Point.STATE_PRESS;
						pointList.add(points[i][j]);
						passList.add(i * 3 + j);
					}				
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			boolean valid = false;
			if(listener != null && isDraw){
				valid = listener.OnDrawFinished(passList);
			}
			if(!valid){
				for (Point p:pointList) {
					p.state = Point.STATE_ERROR;
				}
			}
			isDraw = false;
			break;

		default:
			break;
		}
		this.postInvalidate();
		return true;
	}

	private int[] getSelectedPoint() {
		Point pMouse = new Point(mouseX,mouseY);
		for (int i = 0; i < points.length; i++) {
			for (int j = 0; j < points[i].length; j++) {
				if(points[i][j].distance(pMouse) < bitmapR){
					int [] result = new int [2];
					result[0] = i;
					result[1] = j;
					return result;
				}
			}
			
		}
		return null;
	}

	public void resetPoints() {
		passList.clear();
		pointList.clear();
		for (int i = 0; i < points.length; i++)
        {
            for (int j = 0; j < points[i].length; j++)
            {
                points[i][j].state = Point.STATE_NORMOL;
            }
        }
		this.postInvalidate();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		
		super.onDraw(canvas);
		if(!inited){
			init();
		}
		drawPoints(canvas);
		
		if(pointList.size() > 0){ //畫線 2->3,3->5 ...
			Point a = pointList.get(0);
			for (int i = 1;i < pointList.size(); i++)
            {
                Point b = pointList.get(i);
                drawLine(canvas, a, b);
                a = b;
            }
			if(isDraw){ // 	畫最後一個點
				drawLine(canvas, a, new Point(mouseX, mouseY));
			}
		}
	}

	private void drawLine(Canvas canvas, Point a, Point b) {
		if(a.state == Point.STATE_ERROR){
			canvas.drawLine(a.x, a.y, b.x, b.y, errorPaint);
		}
		else if(a.state == Point.STATE_PRESS){
			canvas.drawLine(a.x, a.y, b.x, b.y, pressPaint);
		}
	}

	private void drawPoints(Canvas canvas) {
		for (int i = 0; i < points.length; i++) {
			for (int j = 0; j < points[i].length; j++) {
				if(points[i][j].state == Point.STATE_NORMOL){
					// normol
					canvas.drawBitmap(bitmapPointNormal, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);
				}
				else if(points[i][j].state == Point.STATE_PRESS){
					// press
					canvas.drawBitmap(bitmapPointPress, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);
				}
				else{
					// error
					canvas.drawBitmap(bitmapPointError, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);
				}
			}
			
		}
	}

	private void init() {
		pressPaint.setColor(Color.YELLOW);
		pressPaint.setStrokeWidth(4);
		errorPaint.setColor(Color.RED);
		errorPaint.setStrokeWidth(4);
		
		bitmapPointError = BitmapFactory.decodeResource(getResources(), R.drawable.error);
		bitmapPointNormal = BitmapFactory.decodeResource(getResources(), R.drawable.normal);
		bitmapPointPress = BitmapFactory.decodeResource(getResources(), R.drawable.press);
		
		bitmapR = bitmapPointError.getWidth() / 2; //三種點的大小一樣
		int width = getWidth();
		int height = getHeight();
		int offset = Math.abs(width - height) / 2;
		int offsetX, offsetY;
		int space;
		if(width > height){
			space = height / 4;
			offsetX = offset;
			offsetY = 0;
		}
		else{
			space = width / 4;
			offsetX = 0;
			offsetY = offset;
		}
		points[0][0] = new Point(offsetX +space , offsetY + space);
		points[0][1] = new Point(offsetX + 2*space , offsetY + space);
		points[0][2] = new Point(offsetX + 3 * space , offsetY + space);
		points[1][0] = new Point(offsetX +space, offsetY + 2 * space);
		points[1][1] = new Point(offsetX + 2 * space , offsetY + 2 * space);
		points[1][2] = new Point(offsetX + 3 * space , offsetY + 2 * space);
		points[2][0] = new Point(offsetX +space, offsetY + 3 * space);
		points[2][1] = new Point(offsetX + 2 * space , offsetY + 3 * space);
		points[2][2] = new Point(offsetX + 3 * space , offsetY + 3 * space);
		
		inited = true; //初始化完成
	}
	
	public interface OnDrawFinishedListener{
		boolean OnDrawFinished(List<Integer> passList);
	}
	
	public void setOnDrawFinishedListener(OnDrawFinishedListener listener){
		this.listener = listener;
	}
	

}
</span>