接着第一个Android UI手势密码设计的基础上继续改进,效果图如下
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);
}
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));
}
}
}
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;
}
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));
}
@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;
}
}
}
您可能感兴趣的文章:Android手势密码view学习笔记(二)Android手势密码view学习笔记(一)Android仿支付宝手势密码解锁功能Android自定义UI手势密码终结版Android自定义UI手势密码改进版源码下载Android自定义UI手势密码简单版Android 简易手势密码开源库详解Android自定义控件实现手势密码Android手势密码的实现Android手势密码实现实例代码