首页>代码>安卓客户端开发的锁屏4*4的图案布局源码下载>/锁屏44/src/com/weiqiang/lockpoint/LockPatternView.java
package com.weiqiang.lockpoint;

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

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

@SuppressLint({ "ClickableViewAccessibility", "DrawAllocation" })
public class LockPatternView extends View {
	//监听器
	private OnPatterChangeListner onPatterChangeListner;
	private static int POINT_SIZE = 5;
	// 画笔
	private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
	// 定义九个点
	public Point[][] points = new Point[4][4];
	// 矩阵
	private Matrix matrix = new Matrix();
	private boolean isInit, isSelect, isFinish, movingNoPoint;
	private float width, height, offsetX, offsetY, bitmapR, movingX, movingY;
	private Bitmap pointsNomal, pointsPressed, pointsError, linePressed,
			lineError;
	private List<Point> pointList = new ArrayList<Point>();

	public LockPatternView(Context context) {
		super(context);
	}

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

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

	/**
	 * 初始化九个点
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		if (!isInit) {
			initPoints();
		}
		point2Canvas(canvas);
		if (pointList.size() > 0) {
			// 绘制九宫格里面的点
			Point a = pointList.get(0);
			for (int i = 0; i < pointList.size(); i++) {
				Point b = pointList.get(i);
				line2Canvas(canvas, a, b);
				a = b;
			}
			// 绘制鼠标坐标点
			if (movingNoPoint) {
				line2Canvas(canvas, a, new Point(movingX, movingY));
			}
		}
	}

	/**
	 * 绘制划线
	 * 
	 * @param canvas
	 *            画布
	 * @param a
	 *            第一个点
	 * @param b
	 *            第二个点
	 */
	private void line2Canvas(Canvas canvas, Point a, Point b) {
		// 线的长度
		float lineLength = (float) Point.distance(a, b);
		float degrees = getDegree(a, b);
		canvas.rotate(degrees, a.x, a.y);
		if (a.state == Point.STATE_PRESSED) {
			matrix.setScale(lineLength / linePressed.getWidth(), 1);
			// 矩阵处理线的平移动,从第一个点进行平移
			matrix.postTranslate(a.x - linePressed.getWidth() / 2, a.y- linePressed.getHeight() / 2);
			canvas.drawBitmap(linePressed, matrix, paint);
		} else {
			matrix.setScale(lineLength / lineError.getWidth(), 1);
			// 矩阵处理线的平移动,从第一个点进行平移
			matrix.postTranslate(a.x - lineError.getWidth() / 2, a.y- lineError.getHeight() / 2);
			canvas.drawBitmap(lineError, matrix, paint);
		}
		canvas.rotate(-degrees, a.x, a.y);
	}

	/**
	 * 将点绘制到画布上
	 * 
	 * @param canvas
	 */
	private void point2Canvas(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.state == Point.STATE_PRESSED) {
					canvas.drawBitmap(pointsPressed, point.x - bitmapR, point.y
							- bitmapR, paint);
				} else if (point.state == Point.STATE_ERROR) {
					canvas.drawBitmap(pointsError, point.x - bitmapR, point.y
							- bitmapR, paint);
				} else {
					canvas.drawBitmap(pointsNomal, point.x - bitmapR, point.y
							- bitmapR, paint);
				}
			}
		}
	}

	/**
	 * 初始化点
	 */
	private void initPoints() {
		// 1.获取手机的宽高
		width = getWidth();
		height = getHeight();
		// 2.计算 x,y偏移量

		// 判断手机横屏或者竖屏
		// 横屏
		if (width > height) {
			offsetX = (width - height)/5;
			System.out.println(offsetX);
			width = height;
			// 竖屏
		} else {
			offsetY = (height - width)/5;
			System.out.println(offsetY);
			height = width;
		}
		// 3.获取图片资源
		pointsNomal = BitmapFactory.decodeResource(getResources(),R.drawable.point_nomal);
		pointsPressed = BitmapFactory.decodeResource(getResources(),R.drawable.point_pressed);
		pointsError = BitmapFactory.decodeResource(getResources(),R.drawable.point_error);
		linePressed = BitmapFactory.decodeResource(getResources(),R.drawable.line_pressed);
		lineError = BitmapFactory.decodeResource(getResources(),R.drawable.line_error);
		// 4. 绘制点
		// 第一行
		points[0][0] = new Point(offsetX + width / 5, offsetY + width / 5);
		points[0][1] = new Point(offsetX + width*2/5, offsetY + width / 5);
		points[0][2] = new Point(offsetX + width*3/5, offsetY + width/ 5);
		points[0][3] = new Point(offsetX + width*4/5, offsetY + width/5);
		// 第二行
		points[1][0] = new Point(offsetX + width / 5, offsetY + width *2/5);
		points[1][1] = new Point(offsetX + width*2/ 5, offsetY + width *2/ 5);
		points[1][2] = new Point(offsetX + width*3 / 5, offsetY + width*2/ 5);
		points[1][3] = new Point(offsetX + width*4/5, offsetY + width*2/5  );
		// 第三行
		points[2][0] = new Point(offsetX + width / 5, offsetY + width*3/ 5);
		points[2][1] = new Point(offsetX + width *2/5, offsetY + width*3/ 5);
		points[2][2] = new Point(offsetX + width*3 /5, offsetY + width*3/5);
		points[2][3] = new Point(offsetX + width*4/5, offsetY + width*3/5 );
		//第四行
		points[3][0] = new Point(offsetX + width / 5, offsetY + width*4/5);
		points[3][1] = new Point(offsetX + width *2/5, offsetY + width*4/5);
		points[3][2] = new Point(offsetX + width*3 /5, offsetY + width*4/5);
		points[3][3] = new Point(offsetX + width*4/5, offsetY + width*4/5);
		// 5.处理图片资源的半径
		bitmapR = pointsNomal.getHeight() / 2;
		//6.设置密码
		int index = 1;
		for(Point [] points:this.points){
			for(Point point:points){
				point.index = index;
				index++;
			}
		}
		// 7.初始化完成
		isInit = true;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		movingNoPoint = false;
		isFinish = false;
		movingX = event.getX();
		movingY = event.getY();
		Point point = null;
		switch (event.getAction()) {
		// 按下
		case MotionEvent.ACTION_DOWN:
			//重新绘制
			if (onPatterChangeListner!=null) {
				onPatterChangeListner.onPatterStart(true);
			}
			resets();
			point = checkSelectPoint();
			if (point != null) {
				isSelect = true;
			}
			break;
		// 移动
		case MotionEvent.ACTION_MOVE:
			if (isSelect) {
				point = checkSelectPoint();
				if (point == null) {
					movingNoPoint = true;
				}
			}
			break;
		// 抬起
		case MotionEvent.ACTION_UP:
			isFinish = true;
			isSelect = false;
			break;

		}
		// 选中重复检查
		if (!isFinish && isSelect && point != null) {
			// 交叉点
			if (crossPoint(point)) {
				movingNoPoint = true;
				// 新点
			} else {
				point.state = Point.STATE_PRESSED;
				pointList.add(point);
			}
		}
		// 绘制结束
		if (isFinish) {
			// 绘制不成立
			if (pointList.size() == 1) {
				// 清除集合
				resets();
				// 绘制错误
			} else if (pointList.size() < POINT_SIZE && pointList.size() > 0) {
				errorPoint();
				if(onPatterChangeListner!=null){
					onPatterChangeListner.onPatterChange(null);
				}
				//绘制成功
			}else {
				if(onPatterChangeListner!=null){
					String passString ="";
					for (int i = 0; i < pointList.size(); i++) {
						passString+=pointList.get(i).index;
					}
					if (!TextUtils.isEmpty(passString)) {
						
						onPatterChangeListner.onPatterChange(passString);
					}
				}
			}
		}
		// 刷新View
		postInvalidate();
		return true;
	}

	/**
	 * 交叉点的检查
	 * 
	 * @param point点
	 * @return 是否交叉
	 */
	private boolean crossPoint(Point point) {
		if (pointList.contains(point)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 设置绘制不成立
	 */
	public void resets() {
		for (int i = 0; i < pointList.size(); i++) {
			Point point = pointList.get(i);
			point.state = Point.STATE_NOMAL;
		}
		pointList.clear();
	}

	/**
	 * 设置绘制错误
	 */
	public void errorPoint() {
		for (Point point : pointList) {
			point.state = Point.STATE_ERROR;
		}
	}

	/**
	 * 检查鼠标的点是否和九宫格中的点重合
	 */
	private Point checkSelectPoint() {
		for (int i = 0; i < points.length; i++) {
			for (int j = 0; j < points[i].length; j++) {
				Point point = points[i][j];
				if (Point.with(point.x, point.y, bitmapR, movingX, movingY)) {
					return point;
				}
			}
		}
		return null;
	}

	/**
	 * 自定义的点
	 */
	public static class Point {
		public static int STATE_NOMAL = 0;
		public static int STATE_PRESSED = 1;
		public static int STATE_ERROR = 2;
		public float x, y;
		public int index = 0, state = 0;

		public Point() {
			// TODO Auto-generated constructor stub
		}

		public Point(float x, float y) {
			this.x = x;
			this.y = y;
		}

		/**
		 * 两点的距离
		 * 
		 * @param a
		 *            点a
		 * @param b
		 *            点b
		 * @return 距离
		 */
		public static double distance(Point a, Point b) {
			// X轴差的平方+Y轴差的平方,对和开方
			return Math.sqrt(Math.abs(a.x - b.x) * Math.abs(a.x - b.x)
					+ Math.abs(a.y - b.y) * Math.abs(a.y - b.y));
		}

		/**
		 * 是否重合
		 * 
		 * @param pointX
		 *            参考点的X
		 * @param pointY
		 *            参考点的Y
		 * @param r
		 *            圆的半径
		 * @param movingX
		 *            移动点的X
		 * @param movingY
		 *            移动点的Y
		 * @return 是否重合
		 */
		public static boolean with(float pointX, float pointY, float r,
				float movingX, float movingY) {
			// 开方
			return Math.sqrt((pointX - movingX) * (pointX - movingX)
					+ (pointY - movingY) * (pointY - movingY)) < r;
		}
	}

	/**
	 * 获取角度
	 * 
	 * @param a
	 *            第一个点
	 * @param b
	 *            第二个点
	 * @return 角度
	 */
	public float getDegree(Point a, Point b) {
		float ax = a.x;
		float ay = a.y;
		float bx = b.x;
		float by = b.y;
		float degree = 0;
		if (ax == bx) {// Y轴相等 90度或者270度
			if (by > ay) {
				degree = 90;
			} else if (by < ay) {
				degree = 270;
			}
		} else if (by == ay) {// X轴相等 0度或者180度
			if (bx > ax) {
				degree = 0;
			} else if (bx < ax) {
				degree = 180;
			}
		} else if (bx > ax) {//在Y轴右边270~90
			if(by>ay){//在Y轴下面0~90
				degree = 0;
				degree = degree+switchDegree(Math.abs(by-ay),Math.abs(bx-ax));
			}else if(by<ay){//在Y轴的上边 270~0
				degree = 360;
				degree = degree-switchDegree(Math.abs(by-ay),Math.abs(bx-ax));
			}
		} else if (bx < ax) {//在Y轴左边 90~270
			if(by>ay){//在Y轴下面180~270
				degree = 90;
				degree = degree+switchDegree(Math.abs(bx-ax),Math.abs(by-ay));
			}else if(by<ay){//在Y轴的上边90~180
				degree = 270;
				degree = degree-switchDegree(Math.abs(bx-ax),Math.abs(by-ay));
			}
		}
		return degree;
	}
	private float switchDegree(float x,float y){
		//弧度转化为角度
		return (float) Math.toDegrees(Math.atan2(x, y));
	}
	/**
	 * 图案监听器
	 * @author Administrator
	 *
	 */
	public static interface OnPatterChangeListner{
		/**
		 * 图案改变
		 * @param passString 图案的密码
		 */
		void onPatterChange(String passString);
		/**
		 * 是否开始绘制图案
		 * @param isStart是否重新绘制
		 */
		void onPatterStart(boolean isStart);
	}
	/**
	 * 设置图案监听器
	 * @param onPatterChangeListner
	 */
	public void setPatterChangeListner(OnPatterChangeListner onPatterChangeListner){
		if(onPatterChangeListner!=null){
			this.onPatterChangeListner = onPatterChangeListner;
		}
	}

}
最近下载更多
zzzxxcc  LV6 2020年6月17日
开心的一只鱼  LV8 2020年6月16日
花花滑滑画画瓜瓜  LV9 2020年1月9日
871978898  LV1 2019年12月25日
zb1095876169  LV2 2019年12月24日
藤井旋风  LV4 2019年12月14日
lyt1234567890  LV5 2019年12月4日
1198903926  LV9 2019年11月25日
阿凝是个小可爱  LV14 2019年6月29日
那一丝涟漪  LV8 2019年5月26日
最近浏览更多
wzm123530  LV4 2023年5月30日
xiaoqiaothq  LV2 2023年4月2日
MoerPerfect  LV1 2022年9月2日
GZW012345  LV8 2022年3月21日
674100273  LV1 2021年11月22日
melon_yan  LV2 2021年6月24日
Jason137  LV8 2021年6月9日
ewewrfas  LV2 2021年6月1日
fredemma  LV1 2021年3月29日
sizeking  LV8 2021年3月15日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友