Android自定义UI手势密码改进版
程序员文章站
2024-03-03 23:53:40
接着android ui手势密码设计的基础上继续改进,效果图如下
activity_main.xml
接着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); } /********************************************************* * 绘制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; } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Android指纹解锁方法解析
下一篇: Python实现类的创建与使用方法示例