Android实现手势解锁

来源:互联网 发布:2d图像转3d算法 编辑:程序博客网 时间:2024/06/14 02:08

自己实现过一个手势解锁, 觉得有一点用, 所以贴出来便于以后使用.


需求

     9宫格解锁, 连接节点后, 节点之间会绘制连线. 节点被连接后会变色.

     当手指继续绘制手势时, 最后一个节点会延伸出一条连线跟随手指.

     当手指离开屏幕时开始判断解锁手势是否正确, 若解锁失败, 连线变为红色, 维持1秒(或者手指再次触碰解锁控件) 消失


思路

     按照需求, 可以得知需要根据连线状态来绘制节点以及绘制连线, 并记录连线状态.

     手势连线, 需要根据手指的坐标判定哪个节点被连接, 这里通过计算手指点与节点距离来判定是否激活节点.

     手势执行完毕后, 根据节点连线顺序编号, 调用回调接口, 将手势值返回调用者.


绘制图形     

     这里需要绘制的图形有三类:

            1. 节点.

            2. 节点间连线.

            3. 手指与节点的连线.

     常规的方案

         将以上三类图形状态储存到数据结构, 每次移动手指便进行全盘的重绘. 网上很多的手势解锁实现就是用到这样一个方案.

         这样并不会引起效率问题, 只是会让程序员冤枉多写一些代码. 需要维护三种图形的数据结构变化, 也要注意图层的覆盖顺序问题, 写起来也稍微麻烦. 觉得这样写比较笨, 理解起来也难, 所以并未采用该方案.


     优化的方案

         使用FrameLayout, 创建三个图层, 分别将 节点, 节点间连线, 手指与节点的连线, 这三块需要维护的图形放入不同的图层, 这样一来就简单许多, 并且让android帮程序员处理了图层覆盖顺序问题.

         1. 节点绘制:  创建一个GridLayout, 在GridLayout内放入9个ImageView来代表节点, 响应连线状态时改变ImageView图标.

         2. 节点间连线: 同理, 在连线状态响应时根据节点的变化状态, 根据坐标在该图层绘制连线.

         3. 手指与节点的连线: 随着手指的移动, 将手指划过的最后一个节点的坐标与手指当前坐标进行连线, 


判定节点激活

     这里的判定方式无非是根据手指坐标以及节点中心坐标使用勾股定理计算距离来判定节点是否激活

     常规的方案

            循环所有节点, 计算各节点与手指间距离. 这里计算距离公式为 sqrt( (x-xn)^2 + (y-yn)^2  )  这里 x,y 为手指坐标,  xn, yn为第n个节点坐标.

            当距离小于阈值(这里通常为节点半径), 激活节点.

     优化的方案

            1. 这里9宫格为n*n个正方形组成的大正方形, 可以很方便的根据手指横纵坐标计算出手指落点距离哪个9宫格节点最近, 然后只需要计算和这个最近的9宫格的距离是否小于阈值即可判定是否触发, 减少循环次数. 这里也需要考虑到手指落在9宫格外的情况.

            2. 节点激活距离阈值预先平方, 避免比较距离时需要开平方, 减少计算量.


使用

    极其简单, 无第三方库依赖, 只有几个文件, 很容易加到项目中

    使用方法如下:

     

GestureLockView gestureLockView = (GestureLockView) findViewById(R.id.gestureView); //在xml中添加手势控件gestureLockView.setGestureListener(new GestureLockView.GestureListener() {  //添加回调监听器    @Override    public boolean getGesture(String gestureCode) { //gestureCode 是返回的手势值        if (0 == gestureCode.length()) return true;  //空手势        if (gestureCode.equals("1478")) {  //判断手势值            Toast.makeText(MainActivity.this, "Right!!", Toast.LENGTH_SHORT).show();            return true;        }        Toast.makeText(MainActivity.this, gestureCode + "!=1478", Toast.LENGTH_SHORT).show();        return false;    }});

例子都在工程里面, 使用Android Studio导入即可

  下载链接

1 0