android 自定义ui,Android自定义UI手势密码改进版

接着第一个Android UI手势密码设计的基础上继续改进,效果图如下

25324bf246a87744f1f780ed419eb145.png

activity_main.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context=".MainActivity" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="center"

android:text="请输入密码"

android:id="@+id/text"

/>

android:id="@+id/lock"

android:layout_weight="1"

android:layout_width="match_parent"

android:layout_height="0dp" />

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 pointList = new ArrayList();

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;

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值