700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android自定义九宫格手势解锁组件

Android自定义九宫格手势解锁组件

时间:2022-01-20 02:08:57

相关推荐

Android自定义九宫格手势解锁组件

项目来源

别的不说,先看一下效果图:

九宫格手势图案解锁功能在很多应用中都在使用,本文介绍的组件来自于开源项目PatternLocker的翻写,原工程是使用Kotlin开发的,由于我们项目是使用java开发,所以将原工程使用Java进行了翻写,如果需要kotlin版本的请移步原工程Kotlin版九宫格手势解锁组件,如果需要Java版本的可以点此下载Java版九宫格手势解锁组件。本文主要介绍Java版本九宫格手势解锁组件的使用和实现原理。

支持功能

支持自定义各状态下(未操作时、操作时以及操作出错时)线颜色、填充色和线宽;支持自定义各种状态下(未操作时、操作时以及操作出错时)每个CellView样式和连接线样式;支持设置图案绘制完成后延迟自动清除的时长(默认1秒);支持是否跳过中间点(默认不跳过);支持是否触碰震动反馈(默认不震动);支持指示器辅助控件可选择使用;业务逻辑(至少连点几个点、验证时最多可出错几次等)须自定义

九宫格实现原理

1、九宫格由9个格子组成,首先给每个格子分配id,9个cell的编号如下:

0 1 2

3 4 5

6 7 8

2、给每个格子设置坐标

x 表示该cell的x坐标(点坐标)

y 表示该cell的y坐标(点坐标)

九宫格每个格子x,y 点坐标编号如下:

(0,0) (1,0) (2,0)

(0,1) (1,1) (2,1)

(0,2) (1,2) (2,2)

3、每个格子就是一个圆,所以需要圆心坐标和半径,格子圆心之间距离为3个半径,

centerX 表示该cell的圆心x坐标(相对坐标)

centerY 表示该cell的圆心y坐标(相对坐标)

centerX, centerY 圆心坐标如下:

(radius, radius) (4radius, radius) (7radius, radius)

(radius, 4radius) (4radius, 4radius) (7radius, 4radius)

(radius, 7radius) (4radius, 7radius) (7radius, 7radius)

4、每个格子需要标记是否被选中状态

isHit 表示该cell是否被设置的标记

工程源码介绍

采用自定义View的形式,组件分为两部分,第一部分是指示器View,第二部分是九宫格绘制View。

指示器View:

<com.github.gesture.lockview.PatternIndicatorViewandroid:id="@+id/patternIndicatorView"android:layout_width="50dp"android:layout_height="50dp"android:layout_margin="20dp"/>

九宫格View:

<com.github.gesture.lockview.PatternLockerViewandroid:id="@+id/patternLockerView"android:layout_width="250dp"android:layout_height="250dp" />

这两个view可以拆开使用,如果不需要指示器,就只集成九宫格View即可。由于指示器View和九宫格View逻辑差不多,这里只简单分析一下九宫格View的实现代码。

九宫格View相关类:

PatternLockerView:九宫格View实现类;

DefaultLockerNormalCellView:默认九宫格每一个格子实现类;

DefaultLockerLinkedLineView:默认九宫格连线实现类;

DefaultLockerHitCellView:默认九宫格选中后格子样式实现类;

PatternLockerView

该类主要初始化九宫格9个格子实体,并且重写onDraw和 onMeasure方法,

初始化init方法主要读取attr中的配置属性;

onMeasure方法中选择宽和高的最小值设为View的宽高。

onDraw方法:

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 初始化九宫格每个格子实例this.initCellBeanList();// 画线this.drawLinkedLine(canvas);// 画每个格子this.drawCells(canvas);}

drawLinkedLine方法调用的是DefaultLockerLinkedLineView中画线方法;

drawCells方法调用的是DefaultLockerNormalCellView中画格子方法;

下面分别分析一下如何画格子和画连接线的。

DefaultLockerNormalCellView

画格子方法如下,先画个外圆,然后再画个内圆。

public void draw(Canvas canvas, CellBean cellBean) {int saveCount = canvas.save();// draw outer circlethis.paint.setColor(this.styleDecorator.getNormalColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius(), this.paint);// draw fill circlethis.paint.setColor(this.styleDecorator.getFillColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() - this.styleDecorator.getLineWidth(), this.paint);canvas.restoreToCount(saveCount);}

DefaultLockerHitCellView

绘制选中的格子是先画外圆,再画填充圆,最后画内圆,只是颜色不一样。

@Overridepublic void draw(Canvas canvas, CellBean cellBean, boolean isError) {int saveCount = canvas.save();// draw outer circle 画外圆this.paint.setColor(this.getColor(isError));canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius(), this.paint);// draw fill circle 画填充圆this.paint.setColor(this.styleDecorator.getFillColor());canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() - this.styleDecorator.getLineWidth(), this.paint);// draw inner circle 画内部圆this.paint.setColor(this.getColor(isError));canvas.drawCircle(cellBean.getCenterX(), cellBean.getCenterY(), cellBean.getRadius() / 5f, this.paint);canvas.restoreToCount(saveCount);}

DefaultLockerLinkedLineView

画线方法有点复杂,是通过遍历选中的格子id的集合,使用Path的moveTo移动线坐标,使用lineTo来连线,最后调用drawPath画出线条。

public void draw(Canvas canvas, List<Integer> hitIndexList, List<CellBean> cellBeanList, float endX, float endY, boolean isError) {if (hitIndexList.isEmpty() || cellBeanList.isEmpty()) {return;}int saveCount = canvas.save();Path path = new Path();boolean first = true;for (int i = 0; i < hitIndexList.size(); i++) {// 记录选中的点idInteger it = hitIndexList.get(i);if (0 <= it && it < cellBeanList.size()) {// 获取选中的点CellBean c = cellBeanList.get(it);if (first) {path.reset();// 如果是第一个,则先将起点移动到第一个点path.moveTo(c.getCenterX(), c.getCenterY());first = false;} else {// 连接第一个点到第二个点path.lineTo(c.getCenterX(), c.getCenterY());}}}if ((endX != 0f || endY != 0f) && hitIndexList.size() < 9) {path.lineTo(endX, endY);}this.paint.setColor(this.getColor(isError));this.paint.setStrokeWidth(this.styleDecorator.getLineWidth());canvas.drawPath(path, this.paint);canvas.restoreToCount(saveCount);}

onTouchEvent

主要逻辑实现在onTouchEvent方法中,分别处理手势按下、滑动、抬起状态时的逻辑。处理完逻辑都会调用重绘方法,然后触发onDraw方法,再次执行绘制过程。

按下、滑动、抬起时都会调用updateHitState方法,在updateHitState方法中通过一个List集合来记录被选中的格子的id,绘制的时候再根据该集合更新格子状态。

文章只是粗略介绍一下九宫格手势图案解锁组件的实现原理和过程,深入研究还需要把源码下载下来看一下。

源码下载:

Kotlin版九宫格手势解锁组件

Java版九宫格手势解锁组件

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。