手势密码(二)

代码地址下载

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="请输入密码"
        android:id="@+id/text"
        />

    <com.example.lockpatterview.LockPatterView
        android:id="@+id/lock"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp" />

</LinearLayout>

MainActivity

package com.example.lockpatterview;

import com.example.lockpatterview.LockPatterView.OnPatterChangeLister;

import android.os.Bundle;
import android.text.TextUtils;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity implements OnPatterChangeLister {

	LockPatterView lock;
	TextView text;
	String p = "14789";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		text = (TextView) findViewById(R.id.text);
		lock = (LockPatterView) findViewById(R.id.lock);
		lock.SetOnPatterChangeLister(this);
	}

	@Override
	public void onPatterChange(String passwordStr) {
		if (!TextUtils.isEmpty(passwordStr)) {
			if (passwordStr.equals(p)) {
				text.setText(passwordStr);
			} else {
				text.setText("密码错误");
				lock.errorPoint();
			}
		}else {
			Toast.makeText(MainActivity.this, "至少连接5点", 0).show();
		}

	}

	@Override
	public void onPatterStart(boolean isStart) {
		if (isStart) {
			text.setText("请绘制图案");
		}
	}

}

LockPatterView

package com.example.lockpatterview;

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.Matrix;
import android.graphics.Paint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class LockPatterView extends View {

	private static final int POINT_SIZE = 5;

	private Point[][] points = new Point[3][3];

	private Matrix matrix = new Matrix();

	private float width, height, offstartY, moveX, moveY;;

	private Bitmap bitmap_pressed, bitmap_normal, bitmap_error, bitmap_line,
			bitmap_line_error;

	private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

	private List<Point> pointList = new ArrayList<LockPatterView.Point>();

	private OnPatterChangeLister onPatterChangeLister;

	/**
	 * 构造函数
	 */
	public LockPatterView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public LockPatterView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

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

	/*********************************************************
	 * 绘制9宫格
	 * movePoint代表鼠标在移动,但是不是9宫格里面的点
	 * isInit是否初始化过9个点
	 * isSelect 点位是否被选中状态
	 * isFinish 是否绘制完毕
	 */
	private boolean isInit, isSelect, isFinish, movePoint;

	@Override
	protected void onDraw(Canvas canvas) {
		// 第一次没有初始化就进行初始化,一旦初始化就不在初始化工作了,isInit的意思是---默认没有初始化过
		if (!isInit) {
			// 初始化9个点
			initPoints();
		}
		// 绘制9个点
		points2Canvas(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 (movePoint) {
				line2Canvas(canvas, a, new Point(moveX, moveY));
			}
		}
	}

	/**
	 * 初始化9个点位 获取点位的3种状态 线的2种状态 以及9点的坐标位置 以及初始化密码操作 isInit=
	 * true设置状态--下次不必初始化话工作了
	 */
	private void initPoints() {

		// 获取布局宽高
		width = getWidth();
		height = getHeight();

		// 横屏和竖屏

		offstartY = (height - width) / 2;

		// 图片资源
		bitmap_normal = BitmapFactory.decodeResource(getResources(),
				R.drawable.btn_circle_normal);
		bitmap_pressed = BitmapFactory.decodeResource(getResources(),
				R.drawable.btn_circle_pressed);
		bitmap_error = BitmapFactory.decodeResource(getResources(),
				R.drawable.btn_circle_selected);
		bitmap_line = BitmapFactory.decodeResource(getResources(),
				R.drawable.ddd);
		bitmap_line_error = BitmapFactory.decodeResource(getResources(),
				R.drawable.qqq);

		points[0][0] = new Point(width / 4, offstartY + width / 4);
		points[0][1] = new Point(width / 2, offstartY + width / 4);
		points[0][2] = new Point(width / 4 * 3, offstartY + width / 4);

		points[1][0] = new Point(width / 4, offstartY + width / 4 * 2);
		points[1][1] = new Point(width / 2, offstartY + width / 4 * 2);
		points[1][2] = new Point(width / 4 * 3, offstartY + width / 4 * 2);

		points[2][0] = new Point(width / 4, offstartY + width / 4 * 3);
		points[2][1] = new Point(width / 2, offstartY + width / 4 * 3);
		points[2][2] = new Point(width / 4 * 3, offstartY + width / 4 * 3);

		// 设置密码1--9
		int index = 1;
		for (Point[] points : this.points) {
			for (Point point : points) {
				point.index = index;
				index++;
			}
		}
		// 初始化完成
		isInit = true;
	}

	/**
	 * 将9个点绘制到画布 循环遍历9个点位, 根据3种不同的状态绘制3种不同的9个点位
	 */
	private void points2Canvas(Canvas canvas) {
		// 循环遍历9个点位
		for (int i = 0; i < points.length; i++) {
			// 循环遍历每行的3个点位
			for (int j = 0; j < points[i].length; j++) {
				// 获取依次的某个点位
				Point point = points[i][j];
				if (point.state == Point.STATE_PRESSED) {
					// (Bitmap bitmap, float left, float top, Paint paint)
					canvas.drawBitmap(bitmap_pressed,
							point.x - bitmap_normal.getWidth() / 2, point.y
									- bitmap_normal.getHeight() / 2, paint);
				} else if (point.state == Point.STATE_ERROR) {
					canvas.drawBitmap(bitmap_error,
							point.x - bitmap_normal.getWidth() / 2, point.y
									- bitmap_normal.getHeight() / 2, paint);
				} else {
					canvas.drawBitmap(bitmap_normal,
							point.x - bitmap_normal.getWidth() / 2, point.y
									- bitmap_normal.getHeight() / 2, paint);
				}
			}
		}
	}

	/**
	 * 画线
	 */
	public void line2Canvas(Canvas canvas, Point a, Point b) {
		// 线的长度--2点之间的距离
		float linelength = (float) Point.distance(a, b);
		// 获取2点之间的角度
		float degress = getDegrees(a, b);
		//根据a点进行旋转
		canvas.rotate(degress, a.x, a.y);

		if (a.state == Point.STATE_PRESSED) {
			// xy方向上的缩放比例
			matrix.setScale(linelength / bitmap_line.getWidth(), 1);
			matrix.postTranslate(a.x - bitmap_line.getWidth() / 2, a.y
					- bitmap_line.getHeight() / 2);
			canvas.drawBitmap(bitmap_line, matrix, paint);
		} else {
			matrix.setScale(linelength / bitmap_line.getWidth(), 1);
			matrix.postTranslate(a.x - bitmap_line.getWidth() / 2, a.y
					- bitmap_line.getHeight() / 2);
			canvas.drawBitmap(bitmap_line_error, matrix, paint);
		}
		//画线完毕回归角度
		canvas.rotate(-degress, a.x, a.y);
	}

	// 获取角度
	public float getDegrees(Point pointA, Point pointB) {
		return (float) Math.toDegrees(Math.atan2(pointB.y - pointA.y, pointB.x
				- pointA.x));
	}

	/****************************************************************************
	 * onTouch事件处理
	 */

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		moveX = event.getX();
		moveY = event.getY();

		movePoint = false;
		isFinish = false;

		Point point = null;

		switch (event.getAction()) {
		//只要按下操作,就代表重新绘制界面
		case MotionEvent.ACTION_DOWN:
			if (onPatterChangeLister != null) {
				onPatterChangeLister.onPatterStart(true);
			}
			// 每次按下,都需要清空之前的集合
			resetPoint();
			// 检测是不是在九宫格内
			point = chechSelectPoint();
			if (point != null) {
				//如果按下的位置在9宫格内,就改成状态为true
				isSelect = true;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (isSelect) {
				// 检测是不是在九宫格内
				point = chechSelectPoint();
				if (point == null) {
					movePoint = true;
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			//绘制完毕,点位状态改为未选中
			isFinish = true;
			isSelect = false;
			break;

		}
		// 如果没有绘制完毕,如果九宫格处于选中状态
		if (!isFinish && isSelect && point != null) {
			// 交叉点
			if (crossPoint(point)) {
				movePoint = true;
			} else {// 新点
				point.state = Point.STATE_PRESSED;
				pointList.add(point);
			}
		}

		// 绘制结束
		if (isFinish) {
			// 绘制不成立
			if (pointList.size() == 1) {
				// resetPoint();
				errorPoint();
			} else if (pointList.size() < POINT_SIZE && pointList.size() > 0) {// 绘制错误
				errorPoint();
				if (onPatterChangeLister != null) {
					onPatterChangeLister.onPatterChange(null);
				}
			} else {
				if (onPatterChangeLister != null) {
					String pass = "";
					for (int i = 0; i < pointList.size(); i++) {
						pass = pass + pointList.get(i).index;
					}
					if (!TextUtils.isEmpty(pass)) {
						onPatterChangeLister.onPatterChange(pass);
					}
				}
			}
		}

		postInvalidate();
		return true;
	}

	/**
	 * 重新绘制
	 */
	public void resetPoint() {
		for (int i = 0; i < pointList.size(); i++) {
			Point point = pointList.get(i);
			point.state = Point.STATE_NORMAL;
		}
		pointList.clear();
	}

	/**
	 * 检查是否选中
	 */
	private Point chechSelectPoint() {
		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, bitmap_normal.getWidth() / 2,
						moveX, moveY)) {
					return point;
				}
			}
		}

		return null;
	}

	/**
	 * 交叉点
	 */
	private boolean crossPoint(Point point) {
		if (pointList.contains(point)) {
			return true;
		} else {
			return false;
		}
	}

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

	/***********************************************************************
	 * 自定义的点
	 */
	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 index = 0, state = 0;

		public Point() {
		};

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

		/**
		 * 两点之间的距离
		 */
		public static double distance(Point a, Point b) {
			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));
		}

		/**
		 */
		public static boolean with(float paintX, float pointY, float r,
				float moveX, float moveY) {
			return Math.sqrt((paintX - moveX) * (paintX - moveX)
					+ (pointY - moveY) * (pointY - moveY)) < r;
		}
	}

	/**
	 * 图案监听器
	 */
	public static interface OnPatterChangeLister {
		void onPatterChange(String passwordStr);

		void onPatterStart(boolean isStart);
	}

	/**
	 * 设置图案监听器
	 */
	public void SetOnPatterChangeLister(OnPatterChangeLister changeLister) {
		if (changeLister != null) {
			this.onPatterChangeLister = changeLister;
		}
	}
}
时间: 2024-08-30 15:01:38

手势密码(二)的相关文章

空间手势密码的实现

一.团队介绍 首先还是要介绍一下我们的团队.我们的队名是"来不及了快上车".队长:黄玥.成员:谢园,宋丰年,潘子帅,张帆,高宇轩. 这里是所有队员的链接: 黄玥:http://www.cnblogs.com/hy1234/ 谢园:http://www.cnblogs.com/KKKA/ 宋丰年:http://www.cnblogs.com/Iriya/ 潘子帅:http://www.cnblogs.com/ss961011/ 张帆:http://www.cnblogs.com/ZFyo

iOS下的手势密码实现

一.iOS下的手势 1 #import "ViewController.h" 2 3 @interface ViewController () 4 5 @property (weak, nonatomic) IBOutlet UILabel *genstureLabel; 6 7 8 @end 9 10 @implementation ViewController 11 12 - (void)viewDidLoad { 13 [super viewDidLoad]; 14 15 16

Android手势密码实现

图 二.实现思路: 1. 正上方的提示区域,用一个类(LockIndicator.java)来实现,自定义view来绘制9个提示图标: 2. 手势密码绘制区域,用一个类(GestureContentView.java)来实现,它继承自ViewGroup里面, 添加9个ImageView来表示图标, 在onLayout()方法中设置它们的位置: 3. 手势路径绘制, 用一个类(GestureDrawline.java)来实现,复写onTouchEvent()方法,在这个方法里面监听TouchEve

手势密码源码

// // WPSignPasswordView.h // 网投网 // // Created by wangtouwang on 15/4/9. // Copyright (c) 2015年 wangtouwang. All rights reserved. // #import <UIKit/UIKit.h> @class WPSignPasswordView; @protocol WPSignPasswordDelegate <NSObject> //设置密码 确认成功 @r

Android招财进宝手势密码的实现

这几个月都是在做招财进宝项目,一个高收益低风险的理财APP,有兴趣的可以下载玩玩,收益不错哦!!! 招财进宝下载地址:http://8.shengpay.com/ 前段时间因产品需求,做了一个手势密码,跟支付宝的手势密码类似,这里跟大家分享交流一下我实现的方式吧. 这篇来分享一下绘制手势密码的实现(主要是设置手势密码.校验手势密码): 一.大致界面介绍:                      图1                                                

Appium-实现手势密码登陆

前言: 前几天有人问我,手势登陆如何做?于是我找了一个APP试了试,所以本文来总结使用Python+Appium来实现手势密码登陆APP. 环境: MacOS:10.13.4 Appium-desktop:1.6.1 Xcode:9.3.1 APP:众安保险-iOS版 ---- 一.Appium API -- TouchAction Appium的辅助类,主要针对手势操作,比如滑动.长按.拖动等. 1.按压控件 方法:press() 开始按压一个元素或坐标点(x,y).通过手指按压手机屏幕的某个

[优化]Swift 简简单单实现手机九宫格手势密码 解锁

我去 为毛这篇文章会被移除首页 技术含量还是有点的   如果在此被移除  那就果断离开园子了 之前的文章 Swift 简简单单实现手机九宫格手势密码解锁 1.对之前的绘制线条的方法进行优化 之前是遍历选中点的集合分别的在点之间绘制线条 改进之后使用系统的API一口气将线条绘制出来 2.增加密码错误情况下想某宝一样红色提示和三角形状的路线指示如下图所示 3.遇到的难点主要是三角形的绘制 和 旋转角度的功能 原理就不多说了 真相见代码 转载需要注明出处 http://www.cnblogs.com/

Andriod手势密码破解

★ 引子 之前在Freebuf上看到一片文章讲Andriod的手势密码加密原理,觉得比较有意思,所以就写了一个小程序试试. ★ 原理            Android的手势密码加密原理很简单: 先给屏幕上的每一个点编号(一般是 3 X 3): 00,01,02 03,04,05 06,07,08 注意这里的数字都是十六进制. 假设我沿着左边和下边画了一个 L 字,则手势的点排列顺序 sequence 是 00,03,06,07,08. 然后计算密文 C = SHA-1(sequence),然

HTML5 Canvas简简单单实现手机九宫格手势密码解锁

原文:HTML5 Canvas简简单单实现手机九宫格手势密码解锁 早上花了一个半小时写了一个基于HTML Canvas的手势解锁,主要是为了好玩,可能以后会用到. 思路:根据配置计算出九个点的位置,存入一个数组,当然存入数组的顺序的索引是: 第一行:0   1  2   第二行:3  4  5 第三行:6  7  8 然后就根据这个坐标数组去绘制九个点 再则我们需要一个保存选中点的数组,每当touchmove事件就判断当前触摸点和那个点的距离小于圆的半径  如果为真的话 那么就添加进入选中点的数

支付宝钱包手势密码破解实战

背景 随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物.消费已是人们不可或缺的一个生活习惯了.随着这股浪潮的兴起,安全.便捷的移动支付需求也越来越大.因此,各大互联网公司纷纷推出了其移动支付平台.其中,用的比较多的要数腾讯的微信和阿里的支付宝钱包了.就我而言,平时和同事一起出去AA吃饭,下班回家打车等日常生活都已经离不开这两个支付平台了. 正所谓树大招风,移动支付平台的兴起,也给众多一直徘徊在网络阴暗地带的黑客们又一次重生的机会.因为移动平台刚刚兴起,人们对移动平台的安全认识度还