九点(九宫格)式手势解锁自定义view
来源:互联网 发布:域名证书是什么作用 编辑:程序博客网 时间:2024/09/21 13:19
周末闲着没事,写了个手势解锁的view,实现起来也蛮快的,半天多一点时间就完事。把源码和资源贴出来,给大家分享,希望对大家有用。
效果,就跟手机上的九点手势解锁一样,上个图吧:
过程嘛感觉确实没啥好讲的了,涉及的知识以前的博客都说过了,无非就是canva,paint,touch事件这些,画画圆圈画画线条,剩下的就是细节处理逻辑了。都在代码里,所以这里就主要是贴资源吧。
这个自定义view就一个类,源码如下:
package com.cc.library.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.location.Location;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewTreeObserver;/** * 图案解锁view * Created by zhangyu on 2016-07-15 15:05. */public class UnlockView extends View { private static final String TAG = "UnlockView"; //view宽高 private float width, height; //平均宽高(分三份) private float averageWidth, averageHeight; //九个点的位置数据,从左到右、从上到下 123...789 Location[] locations = new Location[9]; //圆圈半径 private float radius; //绘制密码 private int[] drawingPwd = new int[9]; //正确的密码 private int[] rightPwd; //画笔 private Paint whitePaint, cyanPaint; //已经绘制过了的点个数 private int drawedNumber; //当前正被触摸的点 private Location nowTouchedPosition = new Location(); //监听 private UnlockListener unlockListener; public void setUnlockListener(UnlockListener unlockListener) { this.unlockListener = unlockListener; } public UnlockView(Context context) { super(context); init(); } public UnlockView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public UnlockView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { ViewTreeObserver vto = getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { height = getHeight(); width = getWidth(); Log.d(TAG, "width = " + width + " ,height = " + height); averageWidth = width / 3f; averageHeight = height / 3f; radius = averageHeight > averageWidth ? averageWidth / 5f : averageHeight / 5f; initLocation(); invalidate(); } }); whitePaint = new Paint(); whitePaint.setAntiAlias(true); whitePaint.setColor(Color.parseColor("#ffffff")); whitePaint.setStyle(Paint.Style.STROKE); cyanPaint = new Paint(); cyanPaint.setAntiAlias(true); cyanPaint.setColor(Color.parseColor("#4169E1")); cyanPaint.setStyle(Paint.Style.STROKE); initDrawingPwd(); } private void drawStart() { drawedNumber = 0; } private void drawOver() { //debug StringBuffer sb = new StringBuffer(); for (int i = 0; i < drawingPwd.length; i++) { sb.append(drawingPwd[i] + ","); } Log.i(TAG, "drawingPwd:" + sb.toString()); initLocation(); initDrawingPwd(); drawedNumber = 0; invalidate(); } /** * 初始化绘制密码 */ private void initDrawingPwd() { for (int i = 0; i < 9; i++) { drawingPwd[i] = -1; } } /** * 初始化九个点坐标 */ private void initLocation() { for (int i = 0; i < 9; i++) { locations[i] = new Location(); locations[i].deawed = false; //纵向1、2、3列x坐标 if (i % 3 == 0) { locations[i].x = averageWidth * 0.5f; } else if (i % 3 == 1) { locations[i].x = averageWidth * 1.5f; } else if (i % 3 == 2) { locations[i].x = averageWidth * 2.5f; } //横向1、2、3排y坐标 if (i / 3 == 0) { locations[i].y = averageHeight * 0.5f; } else if (i / 3 == 1) { locations[i].y = averageHeight * 1.5f; } else if (i / 3 == 2) { locations[i].y = averageHeight * 2.5f; } } } @Override protected void onDraw(Canvas canvas) { for (int i = 0; i < 9; i++) { if (!locations[i].deawed) {//没被画 whitePaint.setStrokeWidth(4); canvas.drawPoint(locations[i].x, locations[i].y, whitePaint); whitePaint.setStrokeWidth(1.5f); canvas.drawCircle(locations[i].x, locations[i].y, radius, whitePaint); } else {//被画过了 cyanPaint.setStrokeWidth(8); canvas.drawPoint(locations[i].x, locations[i].y, cyanPaint); cyanPaint.setStrokeWidth(3f); canvas.drawCircle(locations[i].x, locations[i].y, radius, cyanPaint); } int lastestDrawedPoint = -1; if (drawedNumber > 0) lastestDrawedPoint = drawingPwd[drawedNumber - 1]; if (lastestDrawedPoint != -1) { Location lastestDrawedLocation = locations[lastestDrawedPoint];//最新一个被选中的点 cyanPaint.setStrokeWidth(3f); canvas.drawLine(lastestDrawedLocation.x, lastestDrawedLocation.y, nowTouchedPosition.x, nowTouchedPosition.y, cyanPaint); } if (drawedNumber > 1) { for (int j = 0; j < drawedNumber - 1; j++) { cyanPaint.setStrokeWidth(3f); canvas.drawLine(locations[drawingPwd[j]].x, locations[drawingPwd[j]].y, locations[drawingPwd[j + 1]].x, locations[drawingPwd[j + 1]].y, cyanPaint); } } } super.onDraw(canvas); } float moveX, moveY; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: drawStart(); break; case MotionEvent.ACTION_MOVE: moveX = event.getX(); moveY = event.getY(); dealPosition(moveX, moveY); break; case MotionEvent.ACTION_UP: if (unlockListener != null) { unlockListener.drawOver(drawingPwd); if (verificationPwd(rightPwd)) { unlockListener.isPwdRight(true); } else { unlockListener.isPwdRight(false); } } drawOver(); break; } return true; } private void dealPosition(float nowX, float nowY) { nowTouchedPosition.x = nowX; nowTouchedPosition.y = nowY; int nowTouched = getWhichOneBeTouched(nowX, nowY); if (nowTouched != -1) {//触摸到了点上 if (!locations[nowTouched].deawed) {//如果这点没被触摸过 drawingPwd[drawedNumber] = nowTouched; //记录密码 drawedNumber++; //被触摸点数+1 Log.v(TAG, "nowTouched " + nowTouched + " ,drawedNumber = " + drawedNumber); } locations[nowTouched].deawed = true; } invalidate(); } private class Location { public float x = -1, y = -1; public boolean deawed;//是否被画过了 } /** * 获取被触摸到的点 * * @param x 坐标x点 * @param y 坐标y点 * @return 被触摸的坐标点位置 或者-1 */ private int getWhichOneBeTouched(float x, float y) { for (int i = 0; i < locations.length; i++) { double lPowX = Math.pow(Math.abs(x - locations[i].x), 2); double lPowY = Math.pow(Math.abs(y - locations[i].y), 2); if (Math.sqrt(lPowX + lPowY) < radius) return i; } return -1; } /** * 校验密码是否正确 * * @param rightPwd 正确的密码 * @return 正确返回true 否则返回false */ public boolean verificationPwd(int[] rightPwd) { if (rightPwd == null) return false; for (int i = 0; i < rightPwd.length; i++) { if (rightPwd[i] != drawingPwd[i]) return false; } return true; } /** * 获取当前绘制的密码 * * @return */ public int[] getDrawedPwd() { return drawingPwd; } /** * 设置正确的密码 * * @param rightPwd */ public void setRightPwd(int[] rightPwd) { this.rightPwd = rightPwd; } //监听接口 public interface UnlockListener { public void drawOver(int[] pwd); public void isPwdRight(boolean isRight); }}布局(view的宽高你可以随意指定,bg1是效果里那张背景图片):
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg1"> <com.cc.library.view.UnlockView android:id="@+id/unlock_view" android:layout_width="match_parent" android:layout_height="360dp" android:layout_alignParentBottom="true"/></RelativeLayout>
使用:
package com.sz.china.testmoudule;import android.app.Activity;import android.os.Bundle;import android.widget.Toast;import com.cc.library.view.UnlockView;/** * Created by zhangyu on 2016-07-15 14:55. */public class TestUnlockViewActivity extends Activity { private UnlockView unlockView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.unlock_activity); unlockView = (UnlockView) findViewById(R.id.unlock_view); //设置回调监听 unlockView.setUnlockListener(new UnlockView.UnlockListener() { @Override public void drawOver(int[] pwd) {//绘制完成,获取绘制的密码 unlockView.getDrawedPwd(); } @Override public void isPwdRight(boolean isRight) {//密码是否校验正确 if(isRight) Toast.makeText(TestUnlockViewActivity.this,"密码正确",Toast.LENGTH_SHORT).show(); else Toast.makeText(TestUnlockViewActivity.this,"密码错误",Toast.LENGTH_SHORT).show(); } }); int[] pwd = {0,5,7,6}; unlockView.setRightPwd(pwd); //设置密码 }}
资源下载地址:http://download.csdn.net/detail/chen_zhang_yu/9577759
0 0
- 九点(九宫格)式手势解锁自定义view
- 九点(九宫格)式手势解锁自定义view
- 自定义九宫格手势解锁
- 自定义View----Android九宫格手势密码解锁
- android 自定义view实现九宫格手势解锁
- 自定义View----Android九宫格手势密码解锁
- 自定义view之九宫格手势解锁空间
- 自定义View九宫格手势
- 自定义View--九宫格手势
- 手势解锁-九宫格
- 九宫格手势解锁
- 九宫格手势解锁
- Android进阶之自定义View实战(二)九宫格手势解锁实现
- android自定义view之九宫格解锁
- android自定义view之九宫格解锁
- Android九宫格手势解锁
- 自定义view学习-创建自己的九宫格解锁view
- Android手势解锁, 九宫格解锁
- makefile高级用法--make 的运行
- 判断是否是手机端打开的页面
- ios面试题2016(网上资料)
- swift 在函数内改变函数外的值(元组+inout)
- PHP入门(8) 面向对象(3) 接口
- 九点(九宫格)式手势解锁自定义view
- React 入门实例教程
- BZOJ 3172 [Tjoi2013] 单词 [AC自动机模板]
- 如何将自己的代码自动添加版权信息
- 实现equals方法诀窍
- hud 3979 Monster
- 微服务架构下的数据一致性:可靠事件模式
- UITableView的使用样例(简易向)
- linux的用户管理及磁盘挂载