有时候为了程序的安全性,我们经常要采取一些安全措施,就像我们常用的支付宝那样,隔一定的时间再回到应用程序时会让用户利用手势去解锁应用程序,最近由于项目需求,也要求做这样一个功能,当用户切出本应用程序15分钟后回来,让用户手势解锁,整个需求的难点就在如何实现这个手势锁,开始一点头绪也没有,没有一点思路去实现这个手势解锁功能,在google了一番后看了一篇非常好的博客后,按照博主的思路的确是可以实现一个十分不错的手势锁View,也参考了下那位大神的代码,下面是我根据他的思路和代码片段实现的一个自定义手势解锁 View,先看效果图.

这是自定义View的初始效果图:

以下是绘制手势时的效果图:

下面是实现的demo代码:

package com.example.gesturelock;import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;import com.example.gesturelock.GestureLockView.OnGestureFinishListener;public class MyGestureLockView extends View {/*** 不同状态的画笔*/private Paint paintNormal;private Paint paintOnTouch;private Paint paintInnerCycle;private Paint paintLines;private Paint paintKeyError;private MyCycle[] cycles;private Path linePath = new Path();private List<Integer> linedCycles = new ArrayList<Integer>();private OnGestureFinishListener onGestureFinishListener;private String key;private int eventX, eventY;private boolean canContinue = true;private boolean result;private Timer timer;/*** 不同状态下的色值*/private int OUT_CYCLE_NORMAL = Color.rgb(108, 119, 138); // ������Բ��ɫprivate int OUT_CYCLE_ONTOUCH = Color.rgb(025, 066, 103); // ѡ����Բ��ɫprivate int INNER_CYCLE_ONTOUCH = Color.rgb(002, 210, 255); // ѡ����Բ��ɫprivate int LINE_COLOR = Color.argb(127, 002, 210, 255); // ��������ɫprivate int ERROR_COLOR = Color.argb(127, 255, 000, 000);public void setOnGestureFinishListener(OnGestureFinishListener onGestureFinishListener) {this.onGestureFinishListener = onGestureFinishListener;}public void setKey(String key) {this.key = key;}public MyGestureLockView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}public MyGestureLockView(Context context, AttributeSet attrs) {super(context, attrs);init();}public MyGestureLockView(Context context) {super(context);init();}private void init() {paintNormal = new Paint();paintNormal.setAntiAlias(true);paintNormal.setStrokeWidth(3);paintNormal.setStyle(Paint.Style.STROKE);paintOnTouch = new Paint();paintOnTouch.setAntiAlias(true);paintOnTouch.setStrokeWidth(3);paintOnTouch.setStyle(Paint.Style.STROKE);paintInnerCycle = new Paint();paintInnerCycle.setAntiAlias(true);paintInnerCycle.setStyle(Paint.Style.FILL);paintLines = new Paint();paintLines.setAntiAlias(true);paintLines.setStyle(Paint.Style.STROKE);paintLines.setStrokeWidth(6);paintKeyError = new Paint();paintKeyError.setAntiAlias(true);paintKeyError.setStyle(Paint.Style.STROKE);paintKeyError.setStrokeWidth(3);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {// TODO Auto-generated method stubsuper.onLayout(changed, left, top, right, bottom);int perSize = 0;if (cycles == null && (perSize = getWidth() / 6) > 0) {cycles = new MyCycle[9];for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {MyCycle cycle = new MyCycle();cycle.setNum(i * 3 + j);cycle.setOx(perSize * (j * 2 + 1));cycle.setOy(perSize * (i * 2 + 1));cycle.setR(perSize * 0.5f);cycles[i * 3 + j] = cycle;}}}}/*** 绘制所需要绘制的内容*/@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);for (int i = 0; i < cycles.length; i++) {if (!canContinue && !result) {paintOnTouch.setColor(ERROR_COLOR);paintInnerCycle.setColor(ERROR_COLOR);paintLines.setColor(ERROR_COLOR);} else if (cycles[i].isOnTouch()) {paintOnTouch.setColor(OUT_CYCLE_ONTOUCH);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);} else {paintNormal.setColor(OUT_CYCLE_NORMAL);paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);paintLines.setColor(LINE_COLOR);}if (cycles[i].isOnTouch()) {canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),cycles[i].getR(), paintOnTouch);drawInnerBuleCycle(cycles[i], canvas);} else {canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),cycles[i].getR(), paintNormal);}}drawLine(canvas);}/*** 绘制大圆里的小圆* * @param canvas*/private void drawInnerBuleCycle(MyCycle cycle, Canvas canvas) {canvas.drawCircle(cycle.getOx(), cycle.getOy(), cycle.getR() / 3,paintInnerCycle);}private void drawLine(Canvas canvas) {linePath.reset();if (linedCycles.size() > 0) {for (int i = 0; i < linedCycles.size(); i++) {int index = linedCycles.get(i);if (i == 0) {// 设置为整条路径的起点linePath.moveTo(cycles[index].getOx(), cycles[i].getOy());} else {linePath.lineTo(cycles[i].getOx(), cycles[i].getOy());}}linePath.lineTo(eventX, eventY);canvas.drawPath(linePath, paintLines);}}/*** 根据手择时触摸点的不同,修改对应的状态值*/@Overridepublic boolean onTouchEvent(MotionEvent event) {if (canContinue) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:eventX = (int) event.getX();eventY = (int) event.getY();for (int i = 0; i < cycles.length; i++) {if (cycles[i].isPointIn(eventX, eventY)) {cycles[i].setOnTouch(true);if (!linedCycles.contains(cycles[i].getNum())) {linedCycles.add(cycles[i].getNum());}}}break;case MotionEvent.ACTION_UP:canContinue = false;StringBuffer sb = new StringBuffer();for (int i = 0; i < linedCycles.size(); i++) {sb.append(linedCycles.get(i));}result = key.equals(sb.toString());if (onGestureFinishListener != null) {onGestureFinishListener.OnGestureFinish(result);}timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {// 回到初始状态eventX = eventY = 0;for (int i = 0; i < cycles.length; i++) {cycles[i].setOnTouch(false);}linedCycles.clear();linePath.reset();canContinue = true;postInvalidate();}}, 1000);break;}}invalidate();return true;}
}

自定义圆类:

package com.example.gesturelock;public class MyCycle {private int ox;          // Բ�ĺ�����private int oy;          // Բ��������private float r;         // �뾶����private Integer num;     // ������ֵprivate boolean onTouch; // false=δѡ��public int getOx() {return ox;}public void setOx(int ox) {this.ox = ox;}public int getOy() {return oy;}public void setOy(int oy) {this.oy = oy;}public float getR() {return r;}public void setR(float r) {this.r = r;}public Integer getNum() {return num;}public void setNum(Integer num) {this.num = num;}public boolean isOnTouch() {return onTouch;}public void setOnTouch(boolean onTouch) {this.onTouch = onTouch;}public boolean isPointIn(int x, int y) {double distance = Math.sqrt((x - ox) * (x - ox) + (y - oy) * (y - oy));return distance < r;}
}

思路:

1.自定义一个 View和MyCircle类,将九个MyCircle类的实例绘制到View中.

2.处理onTouch事件,根据不同的事件修改MyCircle实例的状态,并调用更新invaildate更新View

3.重写onDraw()方法,根据不同的状态去重新绘制整个View

android自定义手势解锁View相关推荐

  1. Android 自定义手势解锁View

    直接上代码了: /****@ClassName:GraphicsView*@author:WYL*@Date:2022/9/29*/ class GraphicsView : View {privat ...

  2. android view显示隐藏动画效果,Android 根据手势顶部View自动展示与隐藏效果

    首先来看一下效果: 大体思路如下: 总体布局用了一个自定义的ViewGroup,里面包了两个View(top View,bottomView) 我在bottomView里放了ViewPager,里面又 ...

  3. android自定义滑块解锁,android 滑动解锁

    通过android自定义View实现横向的滑动解锁,1.滑动到中间会自动返回到原始的位置,2.滑动到底部会自动解锁,会触发解锁的回调:首先看效果图如下: 实现以上部分一共分为三部分: 其中背景通过sh ...

  4. android自定义手势,Android编程实现自定义手势的方法详解

    本文实例讲述了Android编程实现自定义手势的方法.分享给大家供大家参考,具体如下: 之前介绍过如何在Android程序中使用手势,主要是系统默认提供的几个手势,这次介绍一下如何自定义手势,以及如何 ...

  5. android自定义手势,Android实现自定义手势和识别手势的功能

    这篇文章主要介绍了Android实现自定义手势和识别手势的功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 1. 先完成自定义手势的Activity 1.1 因 ...

  6. 自定义手势解锁锁控件

    一.控件的使用 模仿市面上app的手势解锁功能,实现的小控件,将控件封装到了一个UIView上 二.核心原理技术 1.触摸事件 (1)UIView的触摸三个触摸响应事件:开始.移动.结束 (2)CGR ...

  7. Android实现手势解锁

    自己实现过一个手势解锁, 觉得有一点用, 所以贴出来便于以后使用. 需求 9宫格解锁, 连接节点后, 节点之间会绘制连线. 节点被连接后会变色. 当手指继续绘制手势时, 最后一个节点会延伸出一条连线跟 ...

  8. android的手势解锁功能,Android应用开发之Android 5秒学会使用手势解锁功能

    本文将带你了解Android应用开发Android 5秒学会使用手势解锁功能,希望本文对大家学Android有所帮助. Android手势解锁 本文讲述的是一个手势解锁的库,可以定制显示隐藏宫格点.路 ...

  9. Android 自定义手势键盘

    自定义手势键盘 手势键盘有三种状态,初始状态.点击状态和错误状态,分别以下列三个图片显示. 2. 数据类CircleArea CircleArea类用来记录手势键盘的信息. static class ...

  10. android自定义滑块解锁,使用Android自定义控件实现滑动解锁九宫格

    本文概述: 滑动解锁九宫格的分析: 1.需要自定义控件: 2.需要重写事件onTouchEvent(); 3.需要给九个点设置序号和坐标,这里用Map类就行: 4.需要判断是否到滑到过九点之一,并存储 ...

最新文章

  1. 使用datatables实现列宽设置、水平滚动条、显示某列部分内容
  2. 为什么二级菜单会被挡住_武夷红茶为什么是二级茶?我们平时喝的红茶会不会被加了糖?...
  3. goodFeaturesToTrack函数
  4. C语言a+++b的问题
  5. 【tensorflow】全连接层函数tf.layers.dense()原理
  6. ubuntu下无法在目录下创建文件夹,权限不足解决办法
  7. jQuery——siblings()方法
  8. 树莓派控制电机转速_怎样用树莓派控制直流电机的方向和速度
  9. Spring Boot 如何解决多个定时任务阻塞问题?
  10. Boost 1.34.0 终于5.12发布了
  11. 单例设计模式 (2)
  12. Android之改变控件的背景及形态
  13. 28.4 kvm介绍 28.5 Centos7上安装KVM 28.6 配置网卡 28.7 创建虚拟机安装CentOS7
  14. 一位大佬对于 Qt 学习的最全总结(三万字干货)
  15. 练习电脑键盘打字最好的网站
  16. Android移动应用程序开发
  17. python项目对接钉钉SDK
  18. 台式计算机读取不了移动硬盘,移动硬盘插入win7电脑一直无法识别的几种原因和解决方法...
  19. 我的世界win10版与java版_我的世界java版和win10版的区别
  20. Excel 合并一个工作簿中的所有工作表

热门文章

  1. Node.js:Webpack
  2. 数据库持久化ORM框架Hibernate、JPA、Mybatis、JOOQ和JDBC Template的比较
  3. JavaScript cookie js cookie设置
  4. PM_敏捷开发 Scrum vs Kanban,如何选择?
  5. ORB-SLAM3学习笔记-基本概念
  6. 论文阅读笔记(六)——GhostNet: More Features from Cheap Operations
  7. 深度学习中的Attention总结
  8. fastText、TextCNN、TextRNN……这里有一套NLP文本分类深度学习方法库供你选择
  9. 利用python批量处理Word文件——正文、标题
  10. PYTHON自动化Day9-发邮件、面向对象、类、私有、继承