Android 简易手势密码开源库详解_第1页
Android 简易手势密码开源库详解_第2页
Android 简易手势密码开源库详解_第3页
Android 简易手势密码开源库详解_第4页
Android 简易手势密码开源库详解_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Android 简易手势密码开源库详解本文主要介绍Android 简易手势密码,这里主要介绍手势密码如何实现及简单的示例代码,有需要的同学可以参考下简介本文介绍一个Android手势密码开源库的使用及实现的详细过程,该开源库主要实现以下几个功能:支持手势密码的绘制,并支持密码保存功能,解锁时自动比对密码给出结果封装了绘制密码的方法,比对两次密码是否一致,可以快捷地进行手势密码的设置可以设置密码输入错误后的重试次数上限可以自定义不同状态下手势密码图案的颜色可以自定义手势密码的触摸点数量(n*n)最近需要用到手势密码解锁功能,找了一些demo感觉用起来都有点麻烦,于是参考一些文章自己造了下轮子,封

2、装了相关的一些方法,使用起来比较便捷。github链接如下,觉得还可以请帮忙star支持下github链接 个人博客使用效果首先看下使用效果:使用方法XML布局文件中使用该控件1234567<com.syd.oden.gesturelock.view.GestureLockViewGroupandroid:id="+id/gesturelock"android:layout_width="match_parent"android:layout_height="match_parent"app:preference_id=&quo

3、t;1"android:layout_marginTop="30dp"app:count="3" />可以设置的一些参数,说明如下:color_no_finger:未触摸时圆形的颜色color_finger_on:触摸时圆形的颜色color_finger_up_correct:输入正确时圆形的颜色color_finger_up_error:出错时圆形的颜色count:收拾密码的圆形数量,n*npreference_id:手势密码保存的id号,不输入或输入-1则使用默认的id初始化?123456private void initGestur

4、e() mGestureLockViewGroup = (GestureLockViewGroup) findViewById(R.id.gesturelock);gestureEventListener();gesturePasswordSettingListener();gestureRetryLimitListener();设置手势密码监听事件123456789101112131415161718192021private void gestureEventListener() mGestureLockViewGroup.setGestureEventListener(new Gestu

5、reEventListener() Overridepublic void onGestureEvent(boolean matched) mylog.d("onGestureEvent matched: " + matched);if (!matched) tv_state.setTextColor(Color.RED);tv_state.setText("手势密码错误"); else if (isReset) isReset = false;Toast.makeText(MainActivity.this, "清除成功!", To

6、ast.LENGTH_SHORT).show();resetGesturePattern(); else tv_state.setTextColor(Color.WHITE);tv_state.setText("手势密码正确"););若已经设置有密码则会进入该回调,在这里对结果进行处理,上面的例子中加入了一个重设密码的处理。手势密码设置1234567891011121314151617181920212223242526272829private void gesturePasswordSettingListener() mGestureLockViewGroup.setG

7、esturePasswordSettingListener(new GesturePasswordSettingListener() Overridepublic boolean onFirstInputComplete(int len) if (len > 3) tv_state.setTextColor(Color.WHITE);tv_state.setText("再次绘制手势密码");return true; else tv_state.setTextColor(Color.RED);tv_state.setText("最少连接4个点,请重新输入!&q

8、uot;);return false;Overridepublic void onSuccess() tv_state.setTextColor(Color.WHITE);Toast.makeText(MainActivity.this, "密码设置成功!", Toast.LENGTH_SHORT).show();tv_state.setText("请输入手势密码解锁!");Overridepublic void onFail() tv_state.setTextColor(Color.RED);tv_state.setText("与上一次绘制

9、不一致,请重新绘制"););若还未设置密码,绘制手势的时候会进入该回调,返回值为绘制的触摸点的数量,onFirstInputComplete中返回true则进入第二手势密码的绘制,两次输入一致后自动保存密码。重试次数超过限制监听123456789private void gestureRetryLimitListener() mGestureLockViewGroup.setGestureUnmatchedExceedListener(3, new GestureUnmatchedExceedListener() Overridepublic void onUnmatchedExce

10、edBoundary() tv_state.setTextColor(Color.RED);tv_state.setText("错误次数过多,请稍后再试!"););若设置了该监听事件,则输入错误有次数限制,超过上限后进入回调,在该回调中进行处理。清除密码的逻辑自己加个判断处理下即可,具体可以看下github上的demo其他的一些API123456public void removePassword() :清除密码public void savePassword() : 保存密码,设置手势密码成功后会自动保存,也可以调用该接口另外设置密码public void getPass

11、word(): 获取密码public void setRetryTimes(int retryTimes) : 设置重试次数上限public boolean isSetPassword() : 返回现在是否已经设置有密码public void resetView() : 将视图Reset在项目中导入该库仅需加入两行代码:在工程的 build.gradle中加入:123456allprojects repositories .maven url "https:/jitpack.io" module的build.gradle中加入依赖:123dependencies compi

12、le 'com.github.autume:GestureLock:1.0.0'总的使用就是这样,是不是很简单!具体实现过程下面讲下实现的过程,如果只是直接拿来用的话也可以略过这部分。自定义手势密码的圆形view这部分主要参考Hongyang大大的博客,稍微修改了一下初始化传入参数123456789public GestureLockView(Context context, int colorNoFingerr, int colorFingerOn, int colorCorrect, int colorError) super(context);this.mColorNoF

13、inger = colorNoFingerr;this.mColorFingerOn = colorFingerOn;this.mColorFingerUpCorrect = colorCorrect;this.mColorFingerUpError = colorError;mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mArrowPath = new Path();根据不同的触摸状态绘制不同颜色的圆12345678910111213141516171819202122232425262728293031323334353637383940Overrid

14、eprotected void onDraw(Canvas canvas) switch (mCurrentStatus) case STATUS_FINGER_ON:/ 绘制外圆mPaint.setStyle(Style.STROKE);mPaint.setColor(mColorFingerOn);mPaint.setStrokeWidth(2);canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);/ 绘制内圆mPaint.setStyle(Style.FILL);canvas.drawCircle(mCenterX, mCente

15、rY, mRadius * mInnerCircleRadiusRate, mPaint);break;case STATUS_FINGER_UP:/ 绘制外圆if (GestureLockViewGroup.isCorrect)mPaint.setColor(mColorFingerUpCorrect);elsemPaint.setColor(mColorFingerUpError);mPaint.setStyle(Style.STROKE);mPaint.setStrokeWidth(2);canvas.drawCircle(mCenterX, mCenterY, mRadius, mPa

16、int);/ 绘制内圆mPaint.setStyle(Style.FILL);canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);drawArrow(canvas);break;case STATUS_NO_FINGER:/ 绘制外圆mPaint.setStyle(Style.STROKE);mPaint.setColor(mColorNoFinger);canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);/ 绘制内圆mPaint

17、.setStyle(Style.FILL);mPaint.setColor(mColorNoFinger);canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);break;绘制箭头12345678910111213141516171819202122232425262728293031Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) super.onMeasure(widthMeas

18、ureSpec, heightMeasureSpec);mWidth = MeasureSpec.getSize(widthMeasureSpec);mHeight = MeasureSpec.getSize(heightMeasureSpec);/ 取长和宽中的小值mWidth = mWidth < mHeight ? mWidth : mHeight;mRadius = mCenterX = mCenterY = mWidth / 2;mRadius -= mStrokeWidth / 2;/ 绘制三角形,初始时是个默认箭头朝上的一个等腰三角形,用户绘制结束后,根据由两个Gestur

19、eLockView决定需要旋转多少度float mArrowLength = mWidth / 2 * mArrowRate;mArrowPath.moveTo(mWidth / 2, mStrokeWidth + 2);mArrowPath.lineTo(mWidth / 2 - mArrowLength, mStrokeWidth + 2 + mArrowLength);mArrowPath.lineTo(mWidth / 2 + mArrowLength, mStrokeWidth + 2 + mArrowLength);mArrowPath.close();mArrowPath.set

20、FillType(Path.FillType.WINDING);private void drawArrow(Canvas canvas) if (mArrowDegree != -1) mPaint.setStyle(Paint.Style.FILL);canvas.save();canvas.rotate(mArrowDegree, mCenterX, mCenterY);canvas.drawPath(mArrowPath, mPaint);canvas.restore();自定义手势密码的ViewGroup加入自定义view的属性1234567891011121314151617181

21、920<?xml version="1.0" encoding="utf-8"?><resources><attr name="color_no_finger" format="color" /><attr name="color_finger_on" format="color" /><attr name="color_finger_up_correct" format="color&quo

22、t; /><attr name="color_finger_up_error" format="color" /><attr name="count" format="integer" /><attr name="preference_id" format="integer" /><declare-styleable name="GestureLockViewGroup"><attr name=&

23、quot;color_no_finger" /><attr name="color_finger_on" /><attr name="color_finger_up_correct" /><attr name="color_finger_up_error" /><attr name="count" /><attr name="preference_id" /></declare-styleable></

24、resources>获取参数及初始化1234567891011121314151617181920212223242526272829303132333435public GestureLockViewGroup(Context context, AttributeSet attrs,int defStyle) super(context, attrs, defStyle);/* 获得所有自定义的参数的值*/TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.GestureLockViewGroup, defSt

25、yle, 0);mNoFingerColor = a.getColor(R.styleable.GestureLockViewGroup_color_no_finger, mNoFingerColor);mFingerOnColor = a.getColor(R.styleable.GestureLockViewGroup_color_finger_on, mFingerOnColor);mFingerUpColorCorrect = a.getColor(R.styleable.GestureLockViewGroup_color_finger_up_correct, mFingerUpCo

26、lorCorrect);mFingerUpColorError = a.getColor(R.styleable.GestureLockViewGroup_color_finger_up_error, mFingerUpColorError);mCount = a.getInt(R.styleable.GestureLockViewGroup_count, mCount);mPrferenceId = a.getInt(R.styleable.GestureLockViewGroup_preference_id, mPrferenceId);a.recycle();/* 获取密码状态*/ges

27、turePreference = new GesturePreference(context, mPrferenceId);password = gesturePreference.ReadStringPreference();Log.d(TAG, "password now is : " + password);isSetPassword = !password.equals("null"); /判断是否已经保存有密码isInPasswordSettingMode = !isSetPassword; /当未设置密码,进入密码设置模式/ 初始化画笔mPa

28、int = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeCap(Paint.Cap.ROUND);mPaint.setStrokeJoin(Paint.Join.ROUND);mPath = new Path();根据参数绘制出圆在onMeasure后调用该方法,绘制圆形矩阵123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354

29、55private GestureLockView mGestureLockViews; /保存所有的GestureLockViewprivate void initViews() / 初始化mGestureLockViewsif (mGestureLockViews = null) mGestureLockViews = new GestureLockViewmCount * mCount;/ 计算每个GestureLockView的宽度mGestureLockViewWidth = (int) (4 * mWidth * 1.0f / (5 * mCount + 1);/计算每个Gestu

30、reLockView的间距mMarginBetweenLockView = (int) (mGestureLockViewWidth * 0.25);/ 设置画笔的宽度为GestureLockView的内圆直径稍微小点mPaint.setStrokeWidth(mGestureLockViewWidth * 0.29f);for (int i = 0; i < mGestureLockViews.length; i+) /初始化每个GestureLockViewmGestureLockViewsi = new GestureLockView(getContext(), mNoFinger

31、Color, mFingerOnColor, mFingerUpColorCorrect, mFingerUpColorError);mGestureLockViewsi.setId(i + 1);/设置参数,主要是定位GestureLockView间的位置RelativeLayout.LayoutParams lockerParams = new RelativeLayout.LayoutParams(mGestureLockViewWidth, mGestureLockViewWidth);/ 不是每行的第一个,则设置位置为前一个的右边if (i % mCount != 0) locker

32、Params.addRule(RelativeLayout.RIGHT_OF,mGestureLockViewsi - 1.getId();/ 从第二行开始,设置为上一行同一位置View的下面if (i > mCount - 1) lockerParams.addRule(RelativeLayout.BELOW,mGestureLockViewsi - mCount.getId();/设置右下左上的边距int rightMargin = mMarginBetweenLockView;int bottomMargin = mMarginBetweenLockView;int leftMa

33、gin = 0;int topMargin = 0;/* 每个View都有右外边距和底外边距 第一行的有上外边距 第一列的有左外边距*/if (i >= 0 && i < mCount)/ 第一行topMargin = mMarginBetweenLockView;if (i % mCount = 0)/ 第一列leftMagin = mMarginBetweenLockView;lockerParams.setMargins(leftMagin, topMargin, rightMargin,bottomMargin);mGestureLockViewsi.set

34、Mode(Mode.STATUS_NO_FINGER);addView(mGestureLockViewsi, lockerParams);在触摸监听中处理不同事件123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103Overridepublic bo

35、olean onTouchEvent(MotionEvent event) int action = event.getAction();int x = (int) event.getX();int y = (int) event.getY();Log.d(TAG, "mTryTimes : " + mTryTimes);/重试次数超过限制,直接返回if (mTryTimes <= 0 && isRetryTimeLimit) return true;switch (action) case MotionEvent.ACTION_DOWN:reset(

36、); / 重置break;case MotionEvent.ACTION_MOVE:drawAndGetSelectedWhenTouchMove(x, y);break;case MotionEvent.ACTION_UP:if (isInPasswordSettingMode) if (gesturePasswordSettingListener != null)setPasswordHandle(); /设置密码 else if (mChoose.size() > 0) isCorrect = checkAnswer(); else return true;if (gestureE

37、ventListener != null) gestureEventListener.onGestureEvent(isCorrect); /将结果回调if (this.mTryTimes = 0) gestureUnmatchedExceedListener.onUnmatchedExceedBoundary(); /超出重试次数,进入回调drawWhenTouchUp();break;invalidate();return true;private void drawAndGetSelectedWhenTouchMove(int x, int y) mPaint.setColor(mFin

38、gerOnColor);mPaint.setAlpha(50);GestureLockView child = getChildIdByPos(x, y);if (child != null) int cId = child.getId();if (!mChoose.contains(cId) mChoose.add(cId);mChooseString = mChooseString + cId;child.setMode(Mode.STATUS_FINGER_ON);/ 设置指引线的起点mLastPathX = child.getLeft() / 2 + child.getRight()

39、/ 2;mLastPathY = child.getTop() / 2 + child.getBottom() / 2;if (mChoose.size() = 1)/ 当前添加为第一个mPath.moveTo(mLastPathX, mLastPathY); else/ 非第一个,将两者使用线连上mPath.lineTo(mLastPathX, mLastPathY);/ 指引线的终点mTmpTarget.x = x;mTmpTarget.y = y;private void drawWhenTouchUp() if (isCorrect) mPaint.setColor(mFingerUp

40、ColorCorrect); else mPaint.setColor(mFingerUpColorError);mPaint.setAlpha(50);Log.d(TAG, "mChoose = " + mChoose);/ 将终点设置位置为起点,即取消指引线mTmpTarget.x = mLastPathX;mTmpTarget.y = mLastPathY;/ 改变子元素的状态为UPsetItemModeUp();/ 计算每个元素中箭头需要旋转的角度for (int i = 0; i + 1 < mChoose.size(); i+) int childId =

41、 mChoose.get(i);int nextChildId = mChoose.get(i + 1);GestureLockView startChild = (GestureLockView) findViewById(childId);GestureLockView nextChild = (GestureLockView) findViewById(nextChildId);int dx = nextChild.getLeft() - startChild.getLeft();int dy = nextChild.getTop() - startChild.getTop();/ 计算

42、角度int angle = (int) Math.toDegrees(Math.atan2(dy, dx) + 90;startChild.setArrowDegree(angle);设置密码处理:1234567891011121314151617private void setPasswordHandle() if (isWaitForFirstInput) if (gesturePasswordSettingListener.onFirstInputComplete(mChooseString.length() firstInputPassword = mChooseString;isWa

43、itForFirstInput = false; else if (firstInputPequals(mChooseString) gesturePasswordSettingListener.onSuccess();savePassword(mChooseString);isInPasswordSettingMode = false; else gesturePasswordSettingListener.onFail();reset();检查手势密码是否正确:123456789public boolean checkAnswer() if (password.equals(mChoose

44、String) return true; else if (isRetryTimeLimit)this.mTryTimes-;return false;重置:123456789private void reset() mCclear();mChooseString = ""mPath.reset();for (GestureLockView gestureLockView : mGestureLockViews) gestureLockView.setMode(Mode.STATUS_NO_FINGER);gestureLockView.setArrowDegree(-1);对外公开的一些方法123456789101112131415161718192021222324252627282930313233343536373839404142public void setGestureEventListener(GestureEventListener gestureEventListener) this.gestureEventListener = gestureEventListener;public void setGestureUnmatchedExceedListener(int retryTimes, Ges

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论