九宫格锁屏模块,九宫格设置密码

要使用九宫格设置密码,先用自定义一个九宫格样式,使用的自定义的view画出九个点,然后重写onMeasure和onDraw,这两个方法,并处理onTouchEvent,这个事件

在Android视图的绘制和布局过程中,onMeasure和onDraw这两个方法的调用顺序是固定的。以下是它们通常的调用顺序:

onMeasure:
当一个视图被添加到布局容器中,或者其布局参数发生变化时,系统会首先调用视图的onMeasure方法。
onMeasure方法的目的是确定视图应该占据的空间大小,即视图的测量宽度和高度。
视图根据自身的内容、布局参数、以及来自父布局的测量规格(MeasureSpec)来决定自己的最佳大小。
一旦确定了测量大小,视图会通过调用setMeasuredDimension方法来设置其测量宽度和高度。
onLayout:
在所有子视图的onMeasure方法被调用并返回之后,父布局会调用其onLayout方法。
onLayout方法的目的是确定每个子视图在父布局中的精确位置。
父布局会根据子视图的测量大小和布局参数,以及自身的布局算法,来计算每个子视图的位置。
父布局会调用每个子视图的layout方法来设置其位置和大小。
onDraw:
在onLayout方法完成之后,如果视图需要绘制内容(即它不是一个透明的或者空的视图),那么它的onDraw方法会被调用。
onDraw方法的目的是在视图的画布上绘制内容。
在onDraw方法中,视图可以使用Canvas对象来绘制形状、文本、图片等。
通常,自定义视图会重写onDraw方法来提供自定义的绘制逻辑。
简而言之,onMeasure首先被调用以确定视图的大小,接着是onLayout来确定视图在父布局中的位置,最后是onDraw来在视图的画布上绘制内容。这个流程是Android视图绘制和布局的核心机制。
当在Android开发中处理View的onTouchEvent事件时,可以通过重写onTouchEvent方法来定义视图如何响应触摸事件。

九宫格锁屏
    public NinePointLineView(Context context) {
        super(context);
        cxt = context; 
        initPaint();
    }

	protected void onDraw(Canvas canvas) {

       //画九点
        drawNinePoint(canvas);
        super.onDraw(canvas);
    }

public class NinePointLineView extends View {
    Paint linePaint = new Paint();
    Paint whiteLinePaint = new Paint();
    Paint textPaint = new Paint();
    Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lock);
    int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
    Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),  R.drawable.indicator_lock_area);
    int selectedBitmapDiameter = selectedBitmap.getWidth();
    int selectedBitmapRadius = selectedBitmapDiameter / 2;
    PointInfo[] points = new PointInfo[9];
    PointInfo startPoint = null;
    int width, height;
    int moveX, moveY;
    boolean isUp = false;
    Context cxt;
    StringBuffer lockString = new StringBuffer();
    public NinePointLineView(Context context) {
        super(context);
        cxt = context;
//		this.setBackgroundColor(Color.WHITE);//设置整个背景
        initPaint();
    }
    public NinePointLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
//		this.setBackgroundColor(Color.WHITE);//设置整个九宫格的背景
        initPaint();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        // 解析测量规格中的模式和大小
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // 根据需要计算视图的宽度和高度

        if (widthMode == MeasureSpec.EXACTLY) {
            // 如果宽度是精确值,则使用它
            width = widthSize;
        } else {
            // 否则,根据内容计算宽度
            width = 400;
        }
        Log.e("NinePointLine", "  heightMode="+heightMode );
        width = widthSize > 600 ? widthSize : 600;
        height = heightSize > 600 ? heightSize : 600;//限制最小区域防止出错
        Log.e("NinePointLine", "onMeasure: Line 53 and width="+width+" and height="+height );
        if (width != 0 && height != 0) {
            initPoints(points);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }
    private int startX = 0, startY = 0;
    @Override
    protected void onDraw(Canvas canvas) {

        //canvas.drawText("passwd:" + lockString, 0, 40, textPaint);
        if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
            drawLine(canvas, startX, startY, moveX, moveY);
        }
        drawNinePoint(canvas);
        super.onDraw(canvas);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean flag = true;
        if (isUp) {
            finishDraw();
            flag = false;
        } else {
            handlingEvent(event);
            flag = true;
        }
        return flag;
    }
    private void handlingEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                moveX = (int) event.getX();
                moveY = (int) event.getY();
                for (PointInfo temp : points) {
                    if (temp.isInMyPlace(moveX, moveY) && temp.isSelected() == false) {
                        temp.setSelected(true);
                        startX = temp.getCenterX();
                        startY = temp.getCenterY();
                        int len = lockString.length();
                        if (len != 0) {
                            int preId = lockString.charAt(len - 1) - 48;
                            points[preId].setNextId(temp.getId());
                        }
                        lockString.append(temp.getId());
                        break;
                    }
                }
                invalidate(0, height - width, width, height);
                break;
            case MotionEvent.ACTION_DOWN:
                int downX = (int) event.getX();
                int downY = (int) event.getY();
                for (PointInfo temp : points) {
                    if (temp.isInMyPlace(downX, downY)) {
                        temp.setSelected(true);
                        startPoint = temp;
                        startX = temp.getCenterX();
                        startY = temp.getCenterY();
                        lockString.append(temp.getId());
                        break;
                    }
                }
                invalidate(0, height - width, width, height);
                break;
            case MotionEvent.ACTION_UP:
                startX = startY = moveX = moveY = 0;
                isUp = true;
                invalidate();
                savePwd();
                break;
            default:
                break;
        }
    }
    private void finishDraw() {
        for (PointInfo temp : points) {
            temp.setSelected(false);
            temp.setNextId(temp.getId());
        }
        lockString.delete(0, lockString.length());
        isUp = false;
        invalidate();
    }
    private void initPoints(PointInfo[] points) {
        int len = points.length;
        int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
        int seletedX = seletedSpacing;
        int seletedY = height - width + seletedSpacing;
        int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
        int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
        for (int i = 0; i < len; i++) {
            if (i == 3 || i == 6) {
                seletedX = seletedSpacing;
                seletedY += selectedBitmapDiameter + seletedSpacing;
                defaultX = seletedX + selectedBitmapRadius
                        - defaultBitmapRadius;
                defaultY += selectedBitmapDiameter + seletedSpacing;
            }
            points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
            seletedX += selectedBitmapDiameter + seletedSpacing;
            defaultX += selectedBitmapDiameter + seletedSpacing;
        }
    }
    private void initPaint() {
        Log.e("NinePointLine", "initPaint: 161" );
        initLinePaint(linePaint);
        initTextPaint(textPaint);
        initWhiteLinePaint(whiteLinePaint);
    }
    /**
     * @param paint
     */
    private void initTextPaint(Paint paint) {
        textPaint.setTextSize(30);
        textPaint.setAntiAlias(true);
        textPaint.setTypeface(Typeface.MONOSPACE);
    }
    /**
     * @param paint
     */
    private void initLinePaint(Paint paint) {
        Log.e("NinePointLine", "initLinePaint: 178" );
        paint.setColor(Color.GRAY);
        paint.setStrokeWidth(30);//设置两个点之间的线的的宽度
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.ROUND);
    }
    /**
     * @param paint
     */
    private void initWhiteLinePaint(Paint paint) {
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(20);//设置两个点之间的线的宽度
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.ROUND);
    }
    /**
     *
     * @param canvas
     */
    private void drawNinePoint(Canvas canvas) {
        if (startPoint != null) {
            drawEachLine(canvas, startPoint);
        }
        for (PointInfo pointInfo : points) {
            if (pointInfo != null) {
                if (pointInfo.isSelected()) {
                    canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
                            pointInfo.getSeletedY(), null);
                }
                canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
                        pointInfo.getDefaultY(), null);
            }
        }
    }
    /**
     * @param canvas
     * @param point
     */
    private void drawEachLine(Canvas canvas, PointInfo point) {
        if (point.hasNextId()) {
            int n = point.getNextId();
            drawLine(canvas, point.getCenterX(), point.getCenterY(),
                    points[n].getCenterX(), points[n].getCenterY());
            drawEachLine(canvas, points[n]);
        }
    }
    /**
     *
     * @param canvas
     * @param startX
     * @param startY
     * @param stopX
     * @param stopY
     */
    private void drawLine(Canvas canvas, float startX, float startY,float stopX, float stopY) {
        canvas.drawLine(startX, startY, stopX, stopY, linePaint);
        canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    }
    /**
     * @author zkwlx
     *
     */
    private class PointInfo {
        private int id;
        private int nextId;
        private boolean selected;
        private int defaultX;
        private int defaultY;
        private int seletedX;
        private int seletedY;
        public PointInfo(int id, int defaultX, int defaultY, int seletedX,
                         int seletedY) {
            this.id = id;
            this.nextId = id;
            this.defaultX = defaultX;
            this.defaultY = defaultY;
            this.seletedX = seletedX;
            this.seletedY = seletedY;
        }
        public boolean isSelected() {
            return selected;
        }
        public void setSelected(boolean selected) {
            this.selected = selected;
        }
        public int getId() {
            return id;
        }
        public int getDefaultX() {
            return defaultX;
        }
        public int getDefaultY() {
            return defaultY;
        }
        public int getSeletedX() {
            return seletedX;
        }
        public int getSeletedY() {
            return seletedY;
        }
        public int getCenterX() {
            return seletedX + selectedBitmapRadius;
        }
        public int getCenterY() {
            return seletedY + selectedBitmapRadius;
        }
        public boolean hasNextId() {
            return nextId != id;
        }
        public int getNextId() {
            return nextId;
        }
        public void setNextId(int nextId) {
            this.nextId = nextId;
        }
        /**
         * @param x
         * @param y
         */
        public boolean isInMyPlace(int x, int y) {
            boolean inX = x > seletedX
                    && x < (seletedX + selectedBitmapDiameter);
            boolean inY = y > seletedY
                    && y < (seletedY + selectedBitmapDiameter);
            return (inX && inY);
        }
    }
    public String getPwd() {//获取本次的密码
        return lockString.toString();
    }
    /**
     * 作用:保存密码并且判断界面的跳转
     * */
    public void savePwd(){
        Intent intent = new Intent();
        SharedPreferences shareDate = cxt.getSharedPreferences("GUE_PWD", MODE_PRIVATE);
        boolean isSetFirst = shareDate.getBoolean("IS_SET_FIRST", false);
        if(isSetFirst){//如果第一次已经设置密码,验证第二次和第一次是否一致
            String pwd = this.getPwd();
            String first_pwd = shareDate.getString("FIRST_PWD", "NO HAVE PWD");
            if(pwd.equals(first_pwd)){//第二次密码和第一次密码一样   设置成功
                shareDate.edit().clear().commit();
                shareDate.edit().putBoolean("IS_SET", true).commit();
                shareDate.edit().putString("GUE_PWD", pwd).commit();
                intent.setClass(cxt, SetPwdResActivity.class);
            }else{//第二次输入的密码和第一次输入的密码不一致

                shareDate.edit().putBoolean("SECOND_ERROR", true).commit();
                intent.setClass(cxt, MainActivity.class);
            }
        }else{//第一次设置手势密码
            shareDate.edit().clear().commit();
            shareDate.edit().putString("FIRST_PWD", this.getPwd()).commit();
            shareDate.edit().putBoolean("IS_SET_FIRST", true).commit();
            intent.setClass(cxt, MainActivity.class);
        }
        cxt.startActivity(intent);
        ((Activity)cxt).finish();

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/392979.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java数字孪生智慧工地数据大屏APP项目源码

目录 智慧工地云平台核心功能 1.劳务管理 2.视频监控 3.安全教育 4.进度管理 5.环境监测 6.塔吊监控 7.升降机监控 8.工地广播 9.深基坑高支模 10.AI识别 11.安全质量 智慧工地建设的价值和意义 危大工程管理 智慧工地聚焦施工现场一线生产活动&#xff0c;利用物…

typescript类型详解

因为介绍了ts的全部类型,所以比较长,各位可以通过目录选择性观看 typescript类型概述typescript 类型注解概念-->监测类型变化 ts类型注解语法ts常用类型原始类型对象类型对象类型_数组类型 ts新增,联合类型ts函数类型ts 函数类型 voidts 函数类型可选参数 ts 对象类型ts 可…

MySQL数据库基础(七):DML数据表操作

文章目录 DML数据表操作 一、数据表的基本操作 1、数据表的创建 2、查询已创建数据表 3、修改数据表信息 ① 数据表字段添加 ② 修改字段名称或字段类型 ③ 删除某个字段 ④ 修改数据表名称 4、删除数据表 二、字段类型详解 1、整数类型 2、浮点类型 3、日期类型…

Pandas.DataFrame.cumprod() 累积乘积 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.2.0 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 传送门&#xff1a; Pandas API参考目录 传送门&#xff1a; Pandas 版本更新及新特性 传送门&…

对前端限流操作(Redis版本)4种算法

固定时间窗口算法 固定时间窗口算法也可以叫做简单计数算法。网上有很多都将计数算法单独抽离出来。但是笔者认为计数算法是一种思想&#xff0c;而固定时间窗口算法是他的一种实现包括下面滑动时间窗口算法也是计数算法的一种实现。因为计数如果不和时间进行绑定的话那么失去…

Redis篇----第五篇

系列文章目录 文章目录 系列文章目录前言一、redis的过期策略以及内存淘汰机制二、Redis 常见性能问题和解决方案?三、为什么Redis的操作是原子性的,怎么保证原子性的?四、Redis事务前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家…

视频基础知识

文章目录 一、视频信号1.1 模拟信号1.2 数字信号 二、视频扫描格式三、视频图像基础四、图像颜色空间1、颜色空间分类2、YUV分类3、YUV存储方式4、YUV类型和存储类型关系5、Color Range6、RBG与YUV互转规范7、RBG与YUV转换公式 五、视频信号显示格式1、标清SD2、高清HD3、全高清…

001kafka源码项目gradle报错UnsupportedClassVersionError-kafka-报错-大数据学习

1 报错提示 java.lang.UnsupportedClassVersionError: org/eclipse/jgit/lib/AnyObjectId has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 如…

Ubuntu 22 安装VNC远程图形界面(GNOME)

0.更新软件源 $ sudo apt update 1.安装VNC $ sudo apt install tightvncserver 2.安装GNOME $ sudo apt install -y gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal ubuntu-desktop 3. 安装支持VNC与Windows之间复制粘贴 $ sudo apt install xcl…

docker (七)-部署容器

实战开始&#xff1a; 1 docker 部署 kafka 集群&#xff0c;并验证 参考 Docker搭建Kafka集群 优秀文档 2 docker 部署 mysql 参考上一篇docker(六) 3.docker 部署 zabbix 参考 docker部署zabbix 优秀文档 BUG&#xff1a;根据这篇文章部署后&#xff0c;发现zabbix-s…

思科命令配置使用方法介绍,全网最全!

你们好&#xff0c;我的网工朋友。 思科作为数通界的老大哥&#xff0c;老一辈网络工程师都是从学习思科开始的吧。 往期也发过命令大全&#xff0c;但是很多朋友反馈拿到命令却不知道从何下手&#xff1f; 今天这篇文章&#xff0c;我将给你介绍思科命令配置的使用方法&#x…

YOLO 损失函数之SIoU 和 Focal 损失在PyTorch中的实现

YOLO (You Only Look Once)系列模型以其实时目标检测能力而闻名,其有效性很大程度上归功于其专门的损失函数。在本文中,我们深入研究了YOLO 演化中不可或缺的各种YOLO 损失函数,重点关注它们在PyTorch中的实现。我们的目标是提供对这些功能的清晰的技术理解,这对于优化模…

【STM32 CubeMX】SPI W25Q64功能实现

文章目录 前言一、内部函数的实现1.1 选中和取消选中SPI Flash1.2 写使能函数1.3 获取读状态1.4 等待就绪状态 二、Flash读写函数实现2.1 读Flash ID2.2 擦除某个扇区2.3 写扇区2.4 读数据 三、测试代码总结 前言 SPI Flash 存储器在嵌入式系统中扮演着重要角色&#xff0c;它…

django定时任务(django-crontab)

目录 一&#xff1a;安装django-crontab&#xff1a; 二&#xff1a;添加django_crontab到你的INSTALLED_APPS设置&#xff1a; 三&#xff1a;运行crontab命令来创建或更新cron作业&#xff1a; 四&#xff1a;定义你的cron作业 五&#xff1a;创建你的管理命令&#xff…

模拟电子技术——同相比例运算放大电路、反向运算比例放大电路、反向加法器电路、差分减法器电路

文章目录 一、同相比例运算放大电路什么是比例运算放大电路线性区与非线性区电压跟随器 二、反向运算比例放大电路什么是反比例运算放大器电路及特点 三、反向加法器电路什么是反向加法器电路及特点及参数计算电路及特点及参数计算 四、差分减法器电路什么是差动减法器 总结 提…

【JVM】打破双亲委派机制

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;JVM ⛺️稳中求进&#xff0c;晒太阳 打破双亲委派机制 打破双亲委派机制三种方法 自定义类加载器 ClassLoader包含了四个核心方法 //由类加载器子类实现&#xff0c;获取二进制数据调用…

使用Erlang/OTP构建容错的软实时Web应用程序

简单介绍 OTP &#xff08;Open Telecom Platform&#xff09; OTP 是包装在Erlang中的一组库程序。OTP构成Erlang的行为机制&#xff08;behaviours&#xff09;&#xff0c;用于编写服务器、有限状态机、事件管理器。不仅如此&#xff0c;OTP的应用行为&#xff08;the appl…

MySQL之json数据操作

1 MySQL之JSON数据 总所周知&#xff0c;mysql5.7以上提供了一种新的字段格式json&#xff0c;大概是mysql想把非关系型和关系型数据库一口通吃&#xff0c;所以推出了这种非常好用的格式&#xff0c;这样&#xff0c;我们的很多基于mongoDB的业务都可以用mysql去实现了。当然…

js设计模式:观察者模式

作用: 和发布订阅模式基本类似。 当某一对象状态发生变化时,所有的观察者都会收到通知。 vue响应式原理就是很经典的案例,数据发生变化,通知各个依赖。 示例: class TaobaoShop{constructor(){this.list []}addSub(name,data){this.list.push({name,data})}pubUser(name,d…

学习数据结构和算法的第9天

题目讲解 移除元素 ​ 给你一个数组nums和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val的元素&#xff0c;并返回移除后数组的新长度。 ​ 不要使用额外的数组空间&#xff0c;你必须仅使用0(1)额外空间并 原地 修改输入数组。 ​ 元素的顺序可以改变。你不需要…