九宫格图案解锁、支付宝解锁、微信钱包解锁
生活随笔
收集整理的這篇文章主要介紹了
九宫格图案解锁、支付宝解锁、微信钱包解锁
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?先來看看效果:
1.九宮格界面實現(xiàn)了密碼的繪制,包括:繪制中、繪制不符合要求、繪制成功3個狀態(tài)
2.繪制過程的監(jiān)聽:繪制錯誤、繪制成功,以及密碼點所對應(yīng)的密碼
3.附上源碼(編碼:UTF-8,可導(dǎo)入到Android Studio中):點擊下載(http://download.csdn.net/detail/fang_guiliang/8449057)
再來看看代碼的實現(xiàn):
第1步:新建自定義屬性,在values文件夾下面新建資源文件,命名為:attrs.xml,用于自定義屬性,其中的代碼如下:
deblcokingMargin:是密碼點之間的間距
<?xml version="1.0" encoding="utf-8"?> <resources><declare-styleable name="DeblockingDot"><attr name="deblcokingMargin" format="dimension"></attr></declare-styleable> </resources>
public DeblockingDot(Context context) {this(context, null);}public DeblockingDot(Context context, AttributeSet attrs) {this(context, attrs, 0);}public DeblockingDot(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DeblockingDot);final int length = array.getIndexCount();for (int i = 0; i < length; i++) {int attr = array.getIndex(i);switch (attr) {case R.styleable.DeblockingDot_deblcokingMargin:margin = array.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 0,getResources().getDisplayMetrics()));break;}}array.recycle();//回收資源initData();//初始化數(shù)據(jù)}intitData()方法中的代碼:獲取圖片資源,創(chuàng)建對象等:
private Bitmap mDefaultBitmap;//默認(rèn)狀態(tài)下的圖private Bitmap mErrorBitmap;//錯誤狀態(tài)下的圖private Bitmap mPressedBitmap;//選中狀態(tài)下的圖private Bitmap mPressedLine;//選中的線private Bitmap mErrorLine;//錯誤的線private Paint mPaint;//畫筆,用于畫線和密碼狀態(tài)的private Matrix mMatrix;//矩陣,用于縮放線private ArrayList<Point> pointList;//密碼點的集合 private void initData() {mDefaultBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_default);mErrorBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_error);mPressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pressed);mPressedLine = BitmapFactory.decodeResource(getResources(), R.drawable.line_pressed);mErrorLine = BitmapFactory.decodeResource(getResources(), R.drawable.line_error);mBitmapR = mDefaultBitmap.getHeight() / 2;mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setAntiAlias(true);//間距必須大于圖標(biāo)的半徑margin = margin < mBitmapR ? mBitmapR : margin;pointList = new ArrayList<Point>();mMatrix = new Matrix();}
public static class Point {//默認(rèn)狀態(tài)public static int STATUS_DEFAULT = 0;//錯誤狀態(tài)public static int STATUS_ERROR = 1;//選中狀態(tài)public static int STATUS_PRESSED = 2;//x軸位置public float x;//y軸位置public float y;//狀態(tài)public int status;//密碼public int password;public Point(float x, float y) {this.x = x;this.y = y;}/*** 判斷兩個點之間的距離是否小于r** @param pointX 點的x軸* @param pointY 點的y軸* @param mouseX 鼠標(biāo)的x軸* @param mouseY 鼠標(biāo)的y軸* @param r* @return*/public static boolean checkPointDistance(float pointX, float pointY, float mouseX, float mouseY, float r) {return Math.sqrt((pointX - mouseX) * (pointX - mouseX) + (pointY - mouseY) * (pointY - mouseY)) < r;}/*** @param a 點a* @param b 點b* @return 兩點之間的距離*/public static double distacne(Point a, Point b) {return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}}
第4步:重寫onDraw方法進(jìn)行繪制,由于需要用到控件的寬高,所以密碼點需要在onDraw初始化
private boolean isInit;//是否初始化過點@Overrideprotected void onDraw(Canvas canvas) {if (!isInit) {initPoint();isInit = true;}points2Canvas(canvas);line2Canvas(canvas);}private Point[][] points;//二維數(shù)組,存放3行3列的密碼點,一共9個值/*** 初始化密碼點*/private void initPoint() {float width = getWidth();float height = getHeight();float offsetsX = 0f;//x軸偏移量float offsetsY = 0f;//Y軸偏移量if (height > width) {offsetsY = (height - width) / 2;height = width;} else {offsetsX = (width - height) / 2;width = height;}points = new Point[3][3];float oneX = offsetsX + margin;//第一豎x軸float twoX = offsetsX + width / 2;//第二豎x軸float threeX = offsetsX + width - margin;//第三豎x軸float oneY = offsetsY + margin;//第一行y軸float twoY = offsetsY + height / 2;//第二行y軸float threeY = offsetsY + width - margin;//第三行y軸//第一行points[0][0] = new Point(oneX, oneY);points[0][1] = new Point(twoX, oneY);points[0][2] = new Point(threeX, oneY);//第二行points[1][0] = new Point(oneX, twoY);points[1][1] = new Point(twoX, twoY);points[1][2] = new Point(threeX, twoY);//第三行points[2][0] = new Point(oneX, threeY);points[2][1] = new Point(twoX, threeY);points[2][2] = new Point(threeX, threeY);//為每個點設(shè)置對應(yīng)的密碼int password = 0;for (Point[] points : this.points) {for (Point point : points) {point.password = ++password;}}}/*** 畫點** @param canvas*/private void points2Canvas(Canvas canvas) {Point point;for (int i = 0; i < points.length; i++) {for (int j = 0; j < points[i].length; j++) {point = points[i][j];if (point.status == Point.STATUS_DEFAULT) {canvas.drawBitmap(mDefaultBitmap, point.x - mBitmapR, point.y - mBitmapR, mPaint);} else if (point.status == Point.STATUS_PRESSED) {canvas.drawBitmap(mPressedBitmap, point.x - mBitmapR, point.y - mBitmapR, mPaint);} else if (point.status == Point.STATUS_ERROR) {canvas.drawBitmap(mErrorBitmap, point.x - mBitmapR, point.y - mBitmapR, mPaint);}}}}
@Overridepublic boolean onTouchEvent(MotionEvent event) {mouseX = event.getX();//手指位置xmouseY = event.getY();//手指位置YisFinish = false;isNeedCanvas = false;Point point = null;switch (event.getAction()) {case MotionEvent.ACTION_DOWN://手指按下resetPoint();point = checkSelectPoint();if (point != null) {isSelected = true;if (listener != null)listener.onActionDown(true);}break;case MotionEvent.ACTION_MOVE:if (isSelected) {//當(dāng)?shù)谝粋€點確認(rèn)后才開始檢查其它點point = checkSelectPoint();if (point == null) {//不是目標(biāo)的點isNeedCanvas = true;}} else {point = checkSelectPoint();if (point != null) {isSelected = true;if (listener != null)listener.onActionDown(true);}}break;case MotionEvent.ACTION_UP:isSelected = false;isFinish = true;break;}//防止重復(fù)選中if (!isFinish && isSelected && point != null) {//在繪制過程中檢測pointif (!pointList.contains(point)) {point.status = Point.STATUS_PRESSED;pointList.add(point);} else {isNeedCanvas = true;}}// 繪制結(jié)束,檢測密碼是否符合規(guī)則if (isFinish) {/*if (pointList.size() == 1) {resetPoint();}*/if (pointList.size() < MIN_POINT_COUNT && pointList.size() > 0) {errorPoint();if (listener != null) {listener.onPointChange(null);}} else {String password = "";for (int i = 0; i < pointList.size(); i++) {password = password + pointList.get(i).password;}if (listener != null) {listener.onPointChange(password);}}}postInvalidate();//重新繪制return true;}/*** 重置點的狀態(tài)*/public void resetPoint() {for (int i = 0; i < pointList.size(); i++) {pointList.get(i).status = Point.STATUS_DEFAULT;}pointList.clear();}/*** 繪制錯誤的點*/private void errorPoint() {for (int i = 0; i < pointList.size(); i++) {pointList.get(i).status = Point.STATUS_ERROR;}}/*** 檢測鼠標(biāo)按下是否接近某個點*/private Point checkSelectPoint() {Point point = null;Point tmpPoint = null;for (int i = 0; i < points.length; i++) {for (int j = 0; j < points[i].length; j++) {tmpPoint = points[i][j];if (Point.checkPointDistance(tmpPoint.x, tmpPoint.y, mouseX, mouseY, mBitmapR)) {point = tmpPoint;}}}return point;}
/*** 畫線** @param canvas*/private void line2Canvas(Canvas canvas) {if (pointList.size() > 0) {Point a = pointList.get(0);Point b;for (int i = 1; i < pointList.size(); i++) {//從第二個點開始,賦給第一個點b = pointList.get(i);line2Canvas(canvas, a, b);a = b;}if (isNeedCanvas) {//需要繼續(xù)畫線條line2Canvas(canvas, a, new Point(mouseX, mouseY));}}}private void line2Canvas(Canvas canvas, Point a, Point b) {float lineLength = (float) Point.distacne(a, b);//需要畫的線的長度float degree = getDegree(a, b);canvas.rotate(degree, a.x, a.y);//旋轉(zhuǎn)畫布,原點發(fā)發(fā)生了變化if (a.status == Point.STATUS_PRESSED) {mMatrix.setScale(lineLength / mPressedLine.getWidth(), 1);//設(shè)置X軸縮放比例mMatrix.postTranslate(a.x - mErrorLine.getWidth() / 2, a.y - mErrorLine.getHeight() / 2);//矩陣平鋪canvas.drawBitmap(mPressedLine, mMatrix, mPaint);} else {mMatrix.setScale(lineLength / mErrorLine.getWidth(), 1);//設(shè)置X軸縮放比例mMatrix.postTranslate(a.x - mErrorLine.getWidth() / 2, a.y - mErrorLine.getHeight() / 2);//矩陣平鋪canvas.drawBitmap(mErrorLine, mMatrix, mPaint);}canvas.rotate(-degree, a.x, a.y);//恢復(fù)畫布,恢復(fù)原點}/*** 獲取線的角度** @param a 點a* @param b 點b* @return 角度*/private float getDegree(Point a, Point b) {float ax = a.x;float ay = a.y;float bx = b.x;float by = b.y;float degress = 0f;if (ax == bx) {//x軸相等,角度為270或者90度if (ay > by) {degress = 270;} else if (ay < by) {degress = 90;}} else if (ay == by) {//y軸相等,角度為0或者180;if (ax > bx) {degress = 180;} else if (ax < bx) {degress = 0;}} else if (ax > bx) {//b在a的左邊,90度到270度if (ay < by) {//b在a下,90度到180度degress = 90 + switchDegress(Math.abs(bx - ax), Math.abs(by - ay));} else if (ay > by) {//b在a的下邊,180度到270度degress = 270 - switchDegress(Math.abs(bx - ax), Math.abs(by - ay));}} else if (ax < bx) {//b在a的右邊,270到90度if (ay > by) {//b在a下邊,360到0degress = 270 + switchDegress(Math.abs(bx - ax), Math.abs(by - ay));} else if (ay < by) {//b在a上邊,0到90degress = 90 - switchDegress(Math.abs(bx - ax), Math.abs(by - ay));}}return degress;} /*** 強制轉(zhuǎn)換為角度** @param x x軸* @param y y軸* @return 角度*/private float switchDegress(float x, float y) {return (float) Math.toDegrees(Math.atan2(x, y));} 以上描述了,整個自定義九宮格圖案的完成思路,代碼也注釋清楚了,角度這塊可能難理解,暫且這樣吧,可以下載源碼Demo整體看下,里面實現(xiàn)了密碼的監(jiān)聽等,可以直接使用到項目中,有疑問的請留言一同討論。
附上源碼:點擊下載(http://download.csdn.net/detail/fang_guiliang/8449057)
總結(jié)
以上是生活随笔為你收集整理的九宫格图案解锁、支付宝解锁、微信钱包解锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【探讨】打码平台是什么意思呢
- 下一篇: 根据accept-language 设置