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

自定义九宫格解锁控件

时间:2021-05-11 17:52:33

相关推荐

自定义九宫格解锁控件

前言

九宫格手势解锁已经是非常常见的手机解锁方式,支付宝等一些软件也都曾经使用过,感觉还是很高大上的。在github已经有很好的开源控件,大家可以去自己搜索,我自己写了一个自定义的九宫格控件,作为练习作业。

效果图

我不会做动图,就凑合看吧……

先贴自定义属性代码

<!-- 九宫格解锁-->

<declare-styleable name="DrawPointLineUnlockView">

<!-- 行数 -->

<attr name="columns" format="integer"/>

<!-- 列数 -->

<attr name="rows" format="integer"/>

<!-- 连线的宽度 -->

<attr name="lineWidth" format="dimension"/>

<!-- 九宫格的大小 -->

<attr name="pointRadius" format="dimension"/>

<!-- 九宫格的颜色 -->

<attr name="pointColor" format="color" />

</declare-styleable>

我把自定义属性的连线宽度,作为了九宫格的实心圆的半径和外面的空心圆的边框宽度。

贴代码

package .interestlibrary.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.CornerPathEffect;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import .interestlibrary.R;import .interestlibrary.view.bean.DrawPoint;/*** Created by li.zhipeng on 16/11/17.* <p>* 九宫格解锁View* <p>* 可以定制颜色和九宫格的数量*/public class DrawPointLineUnlockView extends View {/*** 手势按下时的x坐标*/private float xDown = -1;/*** 手势按下时的y坐标*/private float yDown = -1;/*** 手势y移动时的x坐标*/private float xMove = -1;/*** 手势移动时的y坐标*/private float yMove = -1;/*** 画笔的宽度*/private int lineWidth = 10;/*** 每一个九宫格的大小*/private int pointRadius = 30;/*** 九宫格的横向个数*/private int columeCount = 3;/*** 九宫格的行数*/private int rowCount = 3;/*** 九宫格的颜色*/private int pointColor = Color.parseColor("#000000");/*** 画笔*/private Paint paint;/*** 保存所有的九宫格的点的数组*/private ArrayList<DrawPoint> pointsList;/*** 已经绘制的九宫格的点*/private ArrayList<DrawPoint> drawPoints;/*** 进行判断的点* <p>* 只创建一个,不返回的创建对象,节省内存*/private DrawPoint tempPoint;/*** 是否要进行绘制*/private boolean needDraw;/*** 密码* */private String passward;/*** 解锁解锁回调* */private OnDrawPointUnlockResultListener listener;public void setPassward(String passward){this.passward = passward;}public DrawPointLineUnlockView(Context context) {this(context, null);}public DrawPointLineUnlockView(Context context, AttributeSet attrs) {super(context, attrs);// 获取自定义属性的值TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.DrawPointLineUnlockView);// 画笔的宽度lineWidth = typedArray.getDimensionPixelSize(R.styleable.DrawPointLineUnlockView_lineWidth, 10);// 每一个九宫格的大小pointRadius = typedArray.getDimensionPixelSize(R.styleable.DrawPointLineUnlockView_pointRadius, 30);// 九宫格的横向个数columeCount = typedArray.getInt(R.styleable.DrawPointLineUnlockView_columns, 3);// 九宫格的列数rowCount = typedArray.getInt(R.styleable.DrawPointLineUnlockView_rows, 3);// 九宫格的行数pointColor = typedArray.getColor(R.styleable.DrawPointLineUnlockView_pointColor, Color.parseColor("#000000"));typedArray.recycle();// 防止View不进行绘制,执行onDraw()方法setWillNotDraw(false);pointsList = new ArrayList<>();drawPoints = new ArrayList<>();tempPoint = new DrawPoint(-1, pointRadius, lineWidth);// 初始化画笔paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setColor(pointColor);paint.setStrokeWidth(lineWidth);paint.setPathEffect(new CornerPathEffect(5));}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:xDown = event.getX();yDown = event.getY();// 判断是否这个点是九宫格的某一个点,否则不进行绘制tempPoint.x = xDown;tempPoint.y = yDown;int index = pointsList.indexOf(tempPoint);if (index != -1) {needDraw = true;DrawPoint point = pointsList.get(index);drawPoints.add(point);xDown = point.x;yDown = point.y;} else {needDraw = false;}break;case MotionEvent.ACTION_MOVE:if (needDraw) {xMove = event.getX();yMove = event.getY();// 判断是否这个点是九宫格的某一个点,如果是的话,连接这个点tempPoint.x = xMove;tempPoint.y = yMove;int moveIndex = pointsList.indexOf(tempPoint);// 判断这个点是否是九宫格的点 且 这个点并没有被连接过if (moveIndex != -1 && !drawPoints.contains(tempPoint)) {DrawPoint point = pointsList.get(moveIndex);drawPoints.add(point);}invalidate();}break;case MotionEvent.ACTION_UP:if (needDraw) {xDown = -1;yDown = -1;xMove = -1;yMove = -1;// 监听回调if (listener != null){String unlockResult = returnPwd();listener.onUnlock(unlockResult, unlockResult.equals(passward));}// 清除所有的连接点drawPoints.clear();// 重绘invalidate();}break;}return true;}@Overrideprotected void onDraw(Canvas canvas) {// 画出所有的九宫格的点for (DrawPoint point : pointsList) {point.draw(canvas, paint);}// 如果正在解锁且已经划过了某些九宫格,画出他们之间的连线int size = drawPoints.size() - 1;if (needDraw && size >= 0) {// 只有一个起点,画出第一个点和手指位置的连线if (size == 0) {DrawPoint point = drawPoints.get(0);canvas.drawLine(point.x, point.y, xMove, yMove, paint);}// 多个点,画出点和点之间的连线else {for (int i = 0; i < size; i++) {DrawPoint point = drawPoints.get(i);DrawPoint nextPoint = drawPoints.get(i + 1);canvas.drawLine(point.x, point.y, nextPoint.x, nextPoint.y, paint);}// 画出最后一个点和当前手指位置之间的连线DrawPoint point = drawPoints.get(size);canvas.drawLine(point.x, point.y, xMove, yMove, paint);}}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);// 测量当前的宽高 来绘制指定个数的九宫格float width = getWidth() - pointRadius * 2;float height = getHeight() - pointRadius * 2;// 获取padding值float paddingLeft = getPaddingLeft();float paddingRight = getPaddingRight();float paddingTop = getPaddingTop();float paddingBottom = getPaddingBottom();// 求出每个点的起始位置float xDistance = (width - paddingTop - paddingBottom) / (columeCount - 1);float yDistance = (height - paddingLeft - paddingRight) / (rowCount - 1);// 计算每一个九宫格的圆心for (int i = 0; i < rowCount; i++) {for (int j = 0; j < columeCount; j++) {DrawPoint pointF = new DrawPoint(j + rowCount * i, pointRadius, lineWidth);pointF.y = yDistance * i + pointRadius + paddingTop;pointF.x = xDistance * j + pointRadius + paddingLeft;pointsList.add(pointF);}}}/*** 返回密码* */private String returnPwd(){StringBuilder builder = new StringBuilder();for (DrawPoint point : drawPoints){builder.append(point.getValue());}return builder.toString();}/*** 解锁回调* */public interface OnDrawPointUnlockResultListener{/*** @param passward 解锁的结果密码* @param success 与设置的密码进行匹配的结果* */void onUnlock(String passward, boolean success);}public void setOnDrawPointUnlockResultListener(OnDrawPointUnlockResultListener listener){this.listener = listener;}}

注释写的都是很清楚,不用做过多的解释,关于计算每一个九宫格的中心点,就画图说明一下

图太难画了 ,我们首先减去了九宫格的直径,这样均分了之后,我们就可以得到每一个九宫格的最左边的点,然后用最左边的点加上了半径就得到了x方向的圆心。在y方向上同理。

贴出DrawPoint的代码:

package .interestlibrary.view.bean;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PointF;/*** Created by li.zhipeng on 16/11/18.* <p>* 九宫格的点*/public class DrawPoint extends PointF {/*** 外部的空心圆的半径*/private int pointRadius;/*** 内部的小实心圆的半径*/private int centerPointRadius;/*** 这个点的值,用于解锁密码的匹配*/private int value;public int getValue(){return value;}public DrawPoint(int value, int pointRadius, int centerPointRadius) {this.value = value;this.pointRadius = pointRadius;this.centerPointRadius = centerPointRadius;}public void draw(Canvas canvas, Paint paint) {// 画中心的小实心圆paint.setStyle(Paint.Style.FILL);canvas.drawCircle(x, y, centerPointRadius, paint);// 画外面的空心圆paint.setStyle(Paint.Style.STROKE);canvas.drawCircle(x, y, pointRadius, paint);}/*** 重写此方法,判断是否包含这个点*/@Overridepublic boolean equals(Object o) {if (o instanceof DrawPoint) {// 匹配的误差是 大圆的半径DrawPoint point = (DrawPoint) o;if (Math.abs(this.x - point.x) < pointRadius&& Math.abs(this.y - point.y) < pointRadius) {return true;}}return false;}}

MainActivity:

DrawPointLineUnlockView drawPointLineUnlockView = (DrawPointLineUnlockView) findViewById(R.id.lock);drawPointLineUnlockView.setOnDrawPointUnlockResultListener(new DrawPointLineUnlockView.OnDrawPointUnlockResultListener() {@Overridepublic void onUnlock(String passward, boolean success) {Toast.makeText(MainActivity.this, passward, Toast.LENGTH_SHORT).show();}});

结尾

如果有什么问题和好的建议欢迎大家留言批评指正,尤其是妹纸。

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