Android中图案锁的实现

本文介绍了如何在Android中实现自定义的图案锁功能,包括连线阶段的实现、判断图案是否正确的方法,以及自定义RelativeLayout来处理触摸事件和绘制。文章讨论了如何处理点和线的绘制、记录连接点顺序,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

  很多品牌的Android手机都实现了图案解锁屏幕的功能,有些应用程序出于保护的目的也使用了图案锁(比如支付宝),本文将介绍一种图案锁的实现方式,这种实现的一个优势在于方便扩展和自定义,我们先看一下效果图。
  首先是连线阶段,整个连线为两部分:第一部分是点和点之间的固定线段,第二部分是最后一个点到鼠标移动位置的自由线段。
连线阶段

  接下来是连线结束之后,需要判断图案是否正确,我这里暂时写死的Z字形为正确图案,实际应用时需要记录用户的输入为设置的图案密码。
正确图案

错误图案


  首先我们考虑在哪里完成点和线的绘图。通常我们想到的是写一个自定义的View(即继承自View类),添加onTouchEvent进行控制,同时覆写onDraw()方法,完成绘制。不过我这里没有采用这种方式,考虑到onTouchEvent只能接收在View之上的触摸事件,从上面第一张图中可以看出,如果文字和自定义View平铺摆放的话,那么当手指滑动到文字上面的时候,已经超出了自定义View的范围,因此无法响应触摸事件。虽说有一种补救方式,就是让其他控件和自定义View叠在一起,即摆放在一个FrameLayout里面,不过帧布局对控件位置的控制不像RelativeLayout这样灵活,因此我的实现方式是自定义RelativeLayout,并且在dispatchDraw()方法里,完成点和线的绘制。dispatchDraw()会在布局绘制子控件时调用,具体的可以参考谷歌官方文档。
  首先需要有一个类来记录九个圆点的基本信息。我们可以视为这九个圆是分布于3*3的方格子里面,其中每一个圆位于方格子的中心,在绘制这些圆时,有以下基本信息是要知道的:
1、这些方格子的位置(左上角的X,Y坐标)
2、方格子的边长有多大?
3、方格子的边到圆的边有多大的间隔?
4、圆心的位置(圆心X,Y坐标)
5、圆的半径是多少?
6、这个圆当前应该显示什么颜色?(即圆点的状态)
7、由于我们不可能记录图案整体,而是记录连接点的顺序,那么这个圆所表示的密码值是多少?
  不过上面这7个值是相互依赖的,比如我知道了1和2,就能知道4;知道了2和3,就能知道5。因此,在定义这些值的时候,应当让用户提供充分但不冲突的信息(比如我这里从外部获取的是1、2、3、6、7,而4和5是算出来的)。我在实现的时候,把定义下来就再也用不到的信息写在了一个类里面,把绘制点时还需要获取的信息写在了另一个类里面,并且这个类提供了一些外部调用的方法(实际上这两个类合二为一是完全合理的),代码如下。

package com.liusiqian.patternlock;

/**
 * Créé par liusiqian 15/12/18.
 */
public abstract class PatternPointBase
{
   
    protected int centerX;     //圆心X
    protected int centerY;     //圆心Y
    protected int radius;      //半径
    protected String tag;      //密码标签

    public int status;         //状态

    public static final int STATE_NORMAL = 0;       //正常
    public static final int STATE_SELECTED = 1;     //选中
    public static final int STATE_ERROR = 2;        //错误

    public int getCenterX()
    {
        return centerX;
    }

    public int getCenterY()
    {
        return centerY;
    }

    public boolean isPointArea(double x, double y)
    {
        double len = Math.sqrt(Math.pow(centerX - x, 2) + Math.pow(centerY - y, 2));
        return radius > len;
    }

    public String getTag()
    {
        return tag;
    }

    public int getRadius()
    {
        return radius;
    }
}
package com.liusiqian.patternlock;

/**
 * Créé par liusiqian 15/12/18.
 */
public class PatternPoint extends PatternPointBase
{
   
    protected static final int MIN_SIDE = 20;        //最小边长
    protected static final int MIN_PADDING = 4;        //最小间隔
    protected static final int MIN_RADIUS = 6;        //最小半径

    protected int left, top, side, padding;     //side:边长

    public PatternPoint(int left, int top, int side, int padding, String tag)
    {
        this.left = left;
        this.top = top;
        this.tag = tag;

        if (side < MIN_SIDE)
        {
            side = MIN_SIDE;
        }
        this.side = side;

        if (padding < MIN_PADDING)
        {
            padding = MIN_PADDING;
        }

        radius = side / 2 - padding;
        if (radius < MIN_RADIUS)
        {
            radius = MIN_RADIUS;
            padding = side / 2 -
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值