序言  第一次写Android技术博客,不知道该如何下手。

背景  现在人们越来越重视自己的隐私,对于一些涉及用户隐私的应用,用户可能会希望在应用启动时必须先输入密码。传统的数字式密码记忆繁琐、容易破解,而图案解锁则可以解决这个问题。因此,在应用中添加图案解锁功能,可以提高应用的可靠性,获得用户的信任。

今天,我要介绍的是Android 的屏幕9宫格图形解锁,如果有什么不对的地方,望各位批评指正。直接上代码

1. 首先自定义图形密码控件,继承自View,创建并绘制9个点,并重写onTouchEvent方法。

public class GestureLock extends View {

private Point[][] points = new Point[3][3];
    private boolean inited = false;

private boolean isDraw = false;
    private ArrayList<Point> pointList = new ArrayList<Point>();
    private ArrayList<Integer> passList = new ArrayList<Integer>();

private Bitmap bitmapPointError;
    private Bitmap bitmapPointNormal;
    private Bitmap bitmapPointPress;

private OnDrawFinishedListener listener;

float mouseX, mouseY;

private float bitmapR;

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint pressPaint = new Paint();
    Paint errorPaint = new Paint();

public GestureLock(Context context) {
        super(context);
    }

public GestureLock(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

public GestureLock(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

@Override
    public boolean onTouchEvent(MotionEvent event) {
        mouseX = event.getX();
        mouseY = event.getY();
        int[] ij;
        int i, j;
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                resetPoints();
                ij = getSelectedPoint();
                if (ij != null)
                {
                    isDraw = true;
                    i = ij[0];
                    j = ij[1];
                    points[i][j].state = Point.STATE_PRESS;
                    pointList.add(points[i][j]);
                    passList.add(i * 3 + j);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isDraw)
                {
                    ij = getSelectedPoint();
                    if (ij != null)
                    {
                        i = ij[0];
                        j = ij[1];
                        if(!pointList.contains(points[i][j]))
                        {
                            points[i][j].state = Point.STATE_PRESS;
                            pointList.add(points[i][j]);
                            passList.add(i * 3 + j);
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                boolean valid = false;
                if (listener != null && isDraw)
                {
                    valid = listener.OnDrawFinished(passList);
                }
                if (!valid)
                {
                    for (Point p : pointList)
                    {
                        p.state = Point.STATE_ERROR;
                    }
                }
                isDraw = false;
                break;
        }
        this.postInvalidate();
        return true;
    }

private int[] getSelectedPoint()
    {
        Point pMouse = new Point(mouseX, mouseY);
        for (int i = 0; i < points.length; i++)
        {
            for (int j = 0; j < points[i].length; j++)
            {
                if (points[i][j].distance(pMouse) < bitmapR)
                {
                    int[] result = new int[2];
                    result[0] = i;
                    result[1] = j;
                    return result;
                }
            }
        }
        return null;
    }

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!inited)
        {
            init();
        }

drawPoints(canvas);

if (pointList.size() > 0)
        {
            Point a = pointList.get(0);
            for (int i = 1;i < pointList.size(); i++)
            {
                Point b = pointList.get(i);
                drawLine(canvas, a, b);
                a = b;
            }
            if (isDraw)
            {
                drawLine(canvas, a, new Point(mouseX, mouseY));
            }
        }
    }

private void drawLine(Canvas canvas, Point a, Point b)
    {
        if (a.state == Point.STATE_PRESS)
        {
            canvas.drawLine(a.x, a.y, b.x, b.y, pressPaint);
        }
        else if(a.state == Point.STATE_ERROR)
        {
            canvas.drawLine(a.x, a.y, b.x, b.y, errorPaint);
        }
    }

private void drawPoints(Canvas canvas)
    {
        for (int i = 0; i < points.length; i++)
        {
            for (int j = 0; j < points[i].length; j++)
            {
                if (points[i][j].state == Point.STATE_NORMAL)
                {
                    //Normal
                    canvas.drawBitmap(bitmapPointNormal, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);
                }
                else if (points[i][j].state == Point.STATE_PRESS)
                {
                    //Press
                    canvas.drawBitmap(bitmapPointPress, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);

}
                else {
                    //ERROR
                    canvas.drawBitmap(bitmapPointError, points[i][j].x - bitmapR, points[i][j].y - bitmapR, paint);

}
            }
        }
    }

private void init()
    {
        pressPaint.setColor(Color.YELLOW);
        pressPaint.setStrokeWidth(5);
        errorPaint.setColor(Color.RED);
        errorPaint.setStrokeWidth(5);

bitmapPointError = BitmapFactory.decodeResource(getResources(), R.mipmap.error);
        bitmapPointNormal = BitmapFactory.decodeResource(getResources(), R.mipmap.normal);
        bitmapPointPress = BitmapFactory.decodeResource(getResources(), R.mipmap.press);

bitmapR = bitmapPointError.getHeight() / 2;
        int width = getWidth();
        int height = getHeight();
        int offset = Math.abs(width - height) / 2;
        int offsetX, offsetY;
        int space;
        if(width > height)
        {
            space = height / 4;
            offsetX = offset;
            offsetY = 0;
        }
        else
        {
            space = width / 4;
            offsetX = 0;
            offsetY = offset;
        }
        points[0][0] = new Point(offsetX + space, offsetY + space);
        points[0][1] = new Point(offsetX + space * 2, offsetY + space);
        points[0][2] = new Point(offsetX + space * 3, offsetY + space);

points[1][0] = new Point(offsetX + space, offsetY + space * 2);
        points[1][1] = new Point(offsetX + space * 2, offsetY + space * 2);
        points[1][2] = new Point(offsetX + space * 3, offsetY + space * 2);

points[2][0] = new Point(offsetX + space, offsetY + space * 3);
        points[2][1] = new Point(offsetX + space * 2, offsetY + space * 3);
        points[2][2] = new Point(offsetX + space * 3, offsetY + space * 3);

inited = true;
    }

public void resetPoints()
    {
        passList.clear();
        pointList.clear();
        for (int i = 0; i < points.length; i++)
        {
            for (int j = 0; j < points[i].length; j++)
            {
                points[i][j].state = Point.STATE_NORMAL;
            }
        }
        this.postInvalidate();
    }

public interface OnDrawFinishedListener
    {
        boolean OnDrawFinished(List<Integer> passList);
    }

public void setOnDrawFinishedListener(OnDrawFinishedListener listener)
    {
        this.listener = listener;
    }
}

辅助类 Point.java

public class Point {
    public static int STATE_NORMAL = 0;
    public static int STATE_PRESS = 1;
    public static int STATE_ERROR = 2;

float x;
    float y;
    int state = STATE_NORMAL;

public Point(float x, float y)
    {
        this.x = x;
        this.y = y;
    }

public float distance(Point a)
    {
        float distance = (float)Math.sqrt((x - a.x) * (x - a.x) + (y - a.y) * (y - a.y));
        return distance;
    }

}

2.MainActivity.java  设置和检验密码锁。

public class MainActivity extends ActionBarActivity {

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

Button btn_setting = (Button)findViewById(R.id.button);
        Button btn_lock = (Button)findViewById(R.id.button2);

btn_setting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SettingActivity.class);
                startActivity(intent);
            }
        });

btn_lock.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, LockActivity.class);
                startActivity(intent);
            }
        });

}

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

//noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

return super.onOptionsItemSelected(item);
    }
}

大体核心代码就是这些,后面有demo链接,可根据需要自行下载。

Demo源码下载

Android 图案解锁 9宫格密码解锁相关推荐

  1. android宫格式布局,Android 自定义TextView实现宫格布局,Drawable添加图片并控制宽高...

    上图: 需求: 宫格布局(宽高一致,在屏幕上高度始终更随宽度变化) 图片在上文字在下布局 可以控制图片的宽高 布局完成,废话不多说直接上代码: /** * 时 间 : 2019/7/22 0022 * ...

  2. android 9宫格布局,android 朋友圈9宫格实现

    icon9宫格效果.png 项目优化 2019-10-10 1.有人提出经常new ImageView耗内存, 我现在直接new 9个ImageView,可重复使用这几个ImageView 2.修复图 ...

  3. android 分组宫格菜单,android 九宫格(16宫格)控件

    public class NineRectView extends ViewGroup { private Context ctx; private int wSize,hSize,row,colum ...

  4. android 仿微信9宫格图片

    https://github.com/LukeMee/NineGridlayout 亲测好用

  5. PHP直播平台源码Android自定义View:9宫格图形手势解锁

    9宫格图形解锁的操作就是在9个点上进行的,所以我们先定义一个点类,该类主要用于存储点的信息:坐标,状态,位置. public class Point {//正常状态public static int ...

  6. 9宫格解锁 android_android开发图案解锁学习记录一(九宫格的绘制)

    图案解锁的原理: 九宫格解锁故名思议就是要有九个宫格:然后宫格间进行连线. 首先我们要先绘制九个点(宫格),确定位置,然后绘制不同的图案. 图案分为不同的状态:正常的状态,按下时的状态和错误的状态 当 ...

  7. 快给你的app上锁吧(android图案解锁)

    序言:前两天因为项目的原因,去做了一下仿ios的数字解锁功能,然后写了那篇快给你的app上锁吧(android数字解锁),后来想到应用中常见的还有另外一种解锁就是绘制图案解锁,这两种解锁的布局看起来是 ...

  8. 1、迪文屏基于T5L_C51开发手势6宫格解锁

    演示视频 1.概述 基于迪文屏DMG32240C028-03WTC屏的滑动手势6宫格解锁功能,该功能运用了触摸屏状态读取和坐标读取的功能(系统变量接口0x0016),绘图功能,需要配合变量图标显示等基 ...

  9. 值得推荐的 5 大 Android 手机密码解锁器

    大多数 Android 用户使用唯一密码来保护他们的手机和重要数据.因此,忘记密码并被锁定在手机之外可能会令人沮丧.在这种情况下,使用安卓手机密码解锁器来解决问题是一个明智的选择.本文将介绍2023 ...

最新文章

  1. 摩卡签约印尼五大运营商之一CSM,进军东南亚市场
  2. 怎样解决MySQL数据库主从复制延迟的问题
  3. ashx获取客户端excel文件_Spring Boot实现导出Excel功能
  4. html中如何实现选择存储路径的功能_16687.VSM006分解03_如何打开HTML内嵌图像存储位置...
  5. HDU 1525 类Bash博弈
  6. python编译:setup.py添加.h头文件或者库的搜索路径
  7. thinkphp3.2.3入口文件详解
  8. maya mentray_mental ray渲染器下载
  9. eclipse环境变量配置步骤
  10. 浏览器全屏相关常用代码
  11. 渗透测试技巧总结更新篇2
  12. 图像着色 使用 OpenCV ,深度学习 进行 黑白图像着色
  13. 【深度学习】textCNN论文与原理
  14. php项目管理师什么,《项目管理师》填空题题目答案搜索在线
  15. sql 累计占比_sql 面试题(难题汇总)
  16. mysql 1308_Mysql恢复数据报ERROR1308:LEAVEwithnomatchinglabel_MySQL
  17. JS逆向瑞数4算法专题一
  18. ╭*★*╯浮华一场烟雨梦,叶落无痕情无踪╭*★*╯
  19. 哈工大软件构造Lab2实验
  20. 【转】计算机科学经典之作。。。

热门文章

  1. Vue天地图之图层类型切换
  2. 使用ffmpeg实现单线程异步的视频播放器
  3. 李进良丁守谦论道4G:决不应三国纷争
  4. python多线程批量过滤文件关键字
  5. 年底了,程序员如何谈加薪?
  6. Electron使用electron-updater自动更新
  7. 关于学校熄灯时间的调研
  8. Oracle中游标Cursor介绍
  9. Linux--Smba服务搭建
  10. 储存器RAM、Flash、ROM、HHD简明对比